我发现an article说明了如何在投影坐标中添加点。但在我的实现中,这些点并不构成一个组。字段:
private final BigInteger x;
private final BigInteger y;
private final BigInteger z;
private final BigInteger a;
private final BigInteger b;
private final BigInteger n;
构造
private EllipticCurveProjective(BigInteger x, BigInteger y, BigInteger z, BigInteger a, BigInteger b,
BigInteger n) {
super();
this.x = x;
this.y = y;
this.z = z;
this.a = a;
this.b = b;
this.n = n;
}
随机曲线和点生成器:
public static EllipticCurveProjective generateRandomCurve(BigInteger n) {
BigInteger x = BigInteger.probablePrime(n.bitLength(), new
Random()).mod(n);
BigInteger y = BigInteger.probablePrime(n.bitLength()-1, new Random()).mod(n);
BigInteger a = BigInteger.probablePrime(n.bitLength()-1, new Random()).mod(n);
//This b should fit Weierstrass equation y^2=x^3+ax+b, where b=y^2-x^3-ax
BigInteger b = (y.modPow(TWO, n).subtract(x.modPow(THREE, n)).subtract(a.multiply(x))).mod(n);
return new EllipticCurveProjective(x, y, BigInteger.ONE, a, b, n);
}
加倍和加法:
public EllipticCurveProjective doublePoint() {
/*
* if (Y == 0)
return POINT_AT_INFINITY
*/
if (y.equals(BigInteger.ZERO)) {
return getInfinityPoint();
}
//W = a*Z^2 + 3*X^2
BigInteger w = a.multiply(z.modPow(TWO, n)).add(THREE.multiply(x.modPow(TWO, n)));
//S = Y*Z
BigInteger s = y.multiply(z).mod(n);
//B = X*Y*S
BigInteger b = x.multiply(y).mod(n).multiply(s).mod(n);
//H = W^2 - 8*B
BigInteger h = w.modPow(TWO, n).subtract(EIGHT.multiply(b)).mod(n);
//X' = 2*H*S
BigInteger x3 = TWO.multiply(h).mod(n).multiply(s).mod(n);
//Y' = W*(4*B - H) - 8*Y^2*S^2
BigInteger y3 = w.multiply(FOUR.multiply(b).subtract(h).mod(n)).mod(n)
.subtract(EIGHT.multiply(y.modPow(TWO, n)).multiply(s.modPow(TWO, n)).mod(n)).mod(n);
//Z' = 8*S^3
BigInteger z3 = EIGHT.multiply(s.modPow(THREE, n)).mod(n);
return new EllipticCurveProjective(x3, y3, z3, a, this.b, n);
}
public EllipticCurveProjective addPoint(EllipticCurveProjective ec) {
if (ec.equals(this)) {
return this.doublePoint();
}
//U1 = Y2*Z1
BigInteger u1 = ec.getY().multiply(z).mod(n);
//U2 = Y1*Z2
BigInteger u2 = y.multiply(ec.getZ()).mod(n);
//V1 = X2*Z1
BigInteger v1 = ec.getX().multiply(z).mod(n);
//V2 = X1*Z2
BigInteger v2 = x.multiply(ec.getZ()).mod(n);
// if (V1 == V2)
if (v1.equals(v2)) {
//if (U1 != U2)
if (!u1.equals(u2)) {
return getInfinityPoint();
} else {
// return POINT_DOUBLE(X1, Y1, Z1)
return this.doublePoint();
}
}
//U = U1 - U2
BigInteger u = u1.subtract(u2).mod(n);
//V = V1 - V2
BigInteger v = v1.subtract(v2).mod(n);
//W = Z1*Z2
BigInteger w = z.multiply(ec.getZ()).mod(n);
//A = U^2*W - V^3 - 2*V^2*V2
BigInteger A = u.modPow(TWO, n).multiply(w).mod(n).subtract(v.modPow(THREE, n)).mod(n)
.subtract(TWO.multiply(v.modPow(TWO, n)).multiply(v2)).mod(n);
//X3 = V*A
BigInteger x3 = v.multiply(A).mod(n);
//U*(V^2*V2 - A) - V^3*U2
BigInteger y3 = u.multiply(v.modPow(TWO, n).multiply(v2).mod(n).subtract(A))
.subtract(v.modPow(THREE, n).multiply(u2)).mod(n);
//Z3 = V^3*W
BigInteger z3 = v.modPow(THREE, n).multiply(w).mod(n);
return new EllipticCurveProjective(x3, y3, z3, a, b, n);
}
但如果我这样做:
BigInteger n = BigInteger.probablePrime(32, new Random());
EllipticCurveProjective point = EllipticCurveProjective.generateRandomCurve(n);
//p+p+p
EllipticCurveProjective result1 = point.addPoint(point).addPoint(point);
//p+(p+p)
EllipticCurveProjective result2 = point.addPoint(point.addPoint(point));
System.out.println(result1.equals(result2));
它将返回false,表示p+p+p
不是p+(p+p)
。我的错误在哪里?