diff options
Diffstat (limited to 'core/src')
3 files changed, 95 insertions, 10 deletions
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java index 0d60bdbe..fd29dd47 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java @@ -695,6 +695,7 @@ public abstract class ECCurve switch (coord) { case COORD_AFFINE: + case COORD_HOMOGENEOUS: case COORD_LAMBDA_PROJECTIVE: return true; default: diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java index caffb071..eed2a6ec 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java @@ -1258,6 +1258,41 @@ public abstract class ECPoint return new ECPoint.F2m(curve, X3, Y3, withCompression); } + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Y1 = this.y, Z1 = this.zs[0]; + ECFieldElement Y2 = b.y, Z2 = b.zs[0]; + + boolean Z2IsOne = Z2.bitLength() == 1; + + ECFieldElement U1 = Z1.multiply(Y2); + ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2); + ECFieldElement U = U1.subtract(U2); + ECFieldElement V1 = Z1.multiply(X2); + ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2); + ECFieldElement V = V1.subtract(V2); + + if (V1.equals(V2)) + { + if (U1.equals(U2)) + { + return (ECPoint.F2m)twice(); + } + + return (ECPoint.F2m)curve.getInfinity(); + } + + ECFieldElement VSq = V.square(); + ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2); + ECFieldElement A = U.square().add(U.multiply(V).add(VSq.multiply(curve.getA()))).multiply(W).add(V.multiply(VSq)); + + ECFieldElement X3 = V.multiply(A); + ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2); + ECFieldElement Y3 = VSqZ2.multiply(U.multiply(X1).add(Y1.multiply(V))).add(A.multiply(U.add(V))); + ECFieldElement Z3 = VSq.multiply(V).multiply(W); + + return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, withCompression); + } case ECCurve.COORD_LAMBDA_PROJECTIVE: { if (X1.isZero()) @@ -1370,6 +1405,39 @@ public abstract class ECPoint return addSimple((ECPoint.F2m)b.negate()); } + public ECPoint.F2m tau() + { + if (isInfinity()) + { + return this; + } + + ECCurve curve = getCurve(); + int coord = curve.getCoordinateSystem(); + + ECFieldElement X1 = this.x; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.y; + return new ECPoint.F2m(curve, X1.square(), Y1.square(), withCompression); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.y, Z1 = this.zs[0]; + return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, withCompression); + } + default: + { + throw new UnsupportedOperationException("unsupported coordinate system"); + } + } + } + public ECPoint twice() { if (isInfinity()) @@ -1401,6 +1469,26 @@ public abstract class ECPoint return new ECPoint.F2m(curve, X3, Y3, withCompression); } + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Y1 = this.y, Z1 = this.zs[0]; + + boolean Z1IsOne = Z1.bitLength() == 1; + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1); + ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.multiply(Z1); + + ECFieldElement X1Sq = X1.square(); + ECFieldElement S = X1Sq.add(Y1Z1); + ECFieldElement V = X1Z1; + ECFieldElement vSquared = V.square(); + ECFieldElement h = S.square().add(S.multiply(V)).add(curve.getA().multiply(vSquared)); + + ECFieldElement X3 = V.multiply(h); + ECFieldElement Y3 = h.multiply(S.add(V)).add(X1Sq.square().multiply(V)); + ECFieldElement Z3 = V.multiply(vSquared); + + return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, withCompression); + } case ECCurve.COORD_LAMBDA_PROJECTIVE: { ECFieldElement L1 = this.y, Z1 = this.zs[0]; @@ -1557,6 +1645,11 @@ public abstract class ECPoint ECFieldElement Y = this.y; return new ECPoint.F2m(curve, X, Y.add(X), withCompression); } + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Y = this.y, Z = this.zs[0]; + return new ECPoint.F2m(curve, X, Y.add(X), new ECFieldElement[]{ Z }, withCompression); + } case ECCurve.COORD_LAMBDA_AFFINE: { ECFieldElement L = this.y; diff --git a/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java index 9b24821b..42d67383 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java +++ b/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java @@ -392,16 +392,7 @@ class Tnaf */ public static ECPoint.F2m tau(ECPoint.F2m p) { - if (p.isInfinity()) - { - return p; - } - - ECPoint pn = p.normalize(); - ECFieldElement x = pn.getAffineXCoord(); - ECFieldElement y = pn.getAffineYCoord(); - - return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed()); + return p.tau(); } /** |