aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java')
-rw-r--r--libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java1733
1 files changed, 0 insertions, 1733 deletions
diff --git a/libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java b/libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java
deleted file mode 100644
index 81d7d0957..000000000
--- a/libraries/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java
+++ /dev/null
@@ -1,1733 +0,0 @@
-package org.spongycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * base class for points on elliptic curves.
- */
-public abstract class ECPoint
-{
- protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
-
- protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
- {
- // Cope with null curve, most commonly used by implicitlyCa
- int coord = null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- case ECCurve.COORD_LAMBDA_AFFINE:
- return EMPTY_ZS;
- default:
- break;
- }
-
- ECFieldElement one = curve.fromBigInteger(ECConstants.ONE);
-
- switch (coord)
- {
- case ECCurve.COORD_HOMOGENEOUS:
- case ECCurve.COORD_JACOBIAN:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- return new ECFieldElement[]{ one };
- case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
- return new ECFieldElement[]{ one, one, one };
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- return new ECFieldElement[]{ one, curve.getA() };
- default:
- throw new IllegalArgumentException("unknown coordinate system");
- }
- }
-
- protected ECCurve curve;
- protected ECFieldElement x;
- protected ECFieldElement y;
- protected ECFieldElement[] zs;
-
- protected boolean withCompression;
-
- protected PreCompInfo preCompInfo = null;
-
- protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, getInitialZCoords(curve));
- }
-
- protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
- {
- this.curve = curve;
- this.x = x;
- this.y = y;
- this.zs = zs;
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- protected int getCurveCoordinateSystem()
- {
- // Cope with null curve, most commonly used by implicitlyCa
- return null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
- }
-
- /**
- * Normalizes this point, and then returns the affine x-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- *
- * @deprecated Use getAffineXCoord, or normalize() and getXCoord(), instead
- */
- public ECFieldElement getX()
- {
- return normalize().getXCoord();
- }
-
-
- /**
- * Normalizes this point, and then returns the affine y-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- *
- * @deprecated Use getAffineYCoord, or normalize() and getYCoord(), instead
- */
- public ECFieldElement getY()
- {
- return normalize().getYCoord();
- }
-
- /**
- * Returns the affine x-coordinate after checking that this point is normalized.
- *
- * @return The affine x-coordinate of this point
- * @throws IllegalStateException if the point is not normalized
- */
- public ECFieldElement getAffineXCoord()
- {
- checkNormalized();
- return getXCoord();
- }
-
- /**
- * Returns the affine y-coordinate after checking that this point is normalized
- *
- * @return The affine y-coordinate of this point
- * @throws IllegalStateException if the point is not normalized
- */
- public ECFieldElement getAffineYCoord()
- {
- checkNormalized();
- return getYCoord();
- }
-
- /**
- * Returns the x-coordinate.
- *
- * Caution: depending on the curve's coordinate system, this may not be the same value as in an
- * affine coordinate system; use normalize() to get a point where the coordinates have their
- * affine values, or use getAffineXCoord if you expect the point to already have been
- * normalized.
- *
- * @return the x-coordinate of this point
- */
- public ECFieldElement getXCoord()
- {
- return x;
- }
-
- /**
- * Returns the y-coordinate.
- *
- * Caution: depending on the curve's coordinate system, this may not be the same value as in an
- * affine coordinate system; use normalize() to get a point where the coordinates have their
- * affine values, or use getAffineYCoord if you expect the point to already have been
- * normalized.
- *
- * @return the y-coordinate of this point
- */
- public ECFieldElement getYCoord()
- {
- return y;
- }
-
- public ECFieldElement getZCoord(int index)
- {
- return (index < 0 || index >= zs.length) ? null : zs[index];
- }
-
- public ECFieldElement[] getZCoords()
- {
- int zsLen = zs.length;
- if (zsLen == 0)
- {
- return zs;
- }
- ECFieldElement[] copy = new ECFieldElement[zsLen];
- System.arraycopy(zs, 0, copy, 0, zsLen);
- return copy;
- }
-
- protected ECFieldElement getRawXCoord()
- {
- return x;
- }
-
- protected ECFieldElement getRawYCoord()
- {
- return y;
- }
-
- protected void checkNormalized()
- {
- if (!isNormalized())
- {
- throw new IllegalStateException("point not in normal form");
- }
- }
-
- public boolean isNormalized()
- {
- int coord = this.getCurveCoordinateSystem();
-
- return coord == ECCurve.COORD_AFFINE
- || coord == ECCurve.COORD_LAMBDA_AFFINE
- || isInfinity()
- || zs[0].bitLength() == 1;
- }
-
- /**
- * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
- * coordinates reflect those of the equivalent point in an affine coordinate system.
- *
- * @return a new ECPoint instance representing the same point, but with normalized coordinates
- */
- public ECPoint normalize()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_AFFINE:
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- return this;
- }
- default:
- {
- ECFieldElement Z1 = getZCoord(0);
- if (Z1.bitLength() == 1)
- {
- return this;
- }
-
- return normalize(Z1.invert());
- }
- }
- }
-
- ECPoint normalize(ECFieldElement zInv)
- {
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_HOMOGENEOUS:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- return createScaledPoint(zInv, zInv);
- }
- case ECCurve.COORD_JACOBIAN:
- case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- ECFieldElement zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
- return createScaledPoint(zInv2, zInv3);
- }
- default:
- {
- throw new IllegalStateException("not a projective coordinate system");
- }
- }
- }
-
- protected ECPoint createScaledPoint(ECFieldElement sx, ECFieldElement sy)
- {
- return this.getCurve().createRawPoint(getRawXCoord().multiply(sx), getRawYCoord().multiply(sy), this.withCompression);
- }
-
- public boolean isInfinity()
- {
- return x == null || y == null || (zs.length > 0 && zs[0].isZero());
- }
-
- public boolean isCompressed()
- {
- return this.withCompression;
- }
-
- public boolean equals(ECPoint other)
- {
- if (null == other)
- {
- return false;
- }
-
- ECCurve c1 = this.getCurve(), c2 = other.getCurve();
- boolean n1 = (null == c1), n2 = (null == c2);
- boolean i1 = isInfinity(), i2 = other.isInfinity();
-
- if (i1 || i2)
- {
- return (i1 && i2) && (n1 || n2 || c1.equals(c2));
- }
-
- ECPoint p1 = this, p2 = other;
- if (n1 && n2)
- {
- // Points with null curve are in affine form, so already normalized
- }
- else if (n1)
- {
- p2 = p2.normalize();
- }
- else if (n2)
- {
- p1 = p1.normalize();
- }
- else if (!c1.equals(c2))
- {
- return false;
- }
- else
- {
- // TODO Consider just requiring already normalized, to avoid silent performance degradation
-
- ECPoint[] points = new ECPoint[]{ this, c1.importPoint(p2) };
-
- // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal
- c1.normalizeAll(points);
-
- p1 = points[0];
- p2 = points[1];
- }
-
- return p1.getXCoord().equals(p2.getXCoord()) && p1.getYCoord().equals(p2.getYCoord());
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECPoint))
- {
- return false;
- }
-
- return equals((ECPoint)other);
- }
-
- public int hashCode()
- {
- ECCurve c = this.getCurve();
- int hc = (null == c) ? 0 : ~c.hashCode();
-
- if (!this.isInfinity())
- {
- // TODO Consider just requiring already normalized, to avoid silent performance degradation
-
- ECPoint p = normalize();
-
- hc ^= p.getXCoord().hashCode() * 17;
- hc ^= p.getYCoord().hashCode() * 257;
- }
-
- return hc;
- }
-
- public String toString()
- {
- if (this.isInfinity())
- {
- return "INF";
- }
-
- StringBuffer sb = new StringBuffer();
- sb.append('(');
- sb.append(getRawXCoord());
- sb.append(',');
- sb.append(getRawYCoord());
- for (int i = 0; i < zs.length; ++i)
- {
- sb.append(',');
- sb.append(zs[i]);
- }
- sb.append(')');
- return sb.toString();
- }
-
- public byte[] getEncoded()
- {
- return getEncoded(this.withCompression);
- }
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded(boolean compressed)
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- ECPoint normed = normalize();
-
- byte[] X = normed.getXCoord().getEncoded();
-
- if (compressed)
- {
- byte[] PO = new byte[X.length + 1];
- PO[0] = (byte)(normed.getCompressionYTilde() ? 0x03 : 0x02);
- System.arraycopy(X, 0, PO, 1, X.length);
- return PO;
- }
-
- byte[] Y = normed.getYCoord().getEncoded();
-
- byte[] PO = new byte[X.length + Y.length + 1];
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, X.length);
- System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
- return PO;
- }
-
- protected abstract boolean getCompressionYTilde();
-
- public abstract ECPoint add(ECPoint b);
-
- public abstract ECPoint negate();
-
- public abstract ECPoint subtract(ECPoint b);
-
- public ECPoint timesPow2(int e)
- {
- if (e < 0)
- {
- throw new IllegalArgumentException("'e' cannot be negative");
- }
-
- ECPoint p = this;
- while (--e >= 0)
- {
- p = p.twice();
- }
- return p;
- }
-
- public abstract ECPoint twice();
-
- public ECPoint twicePlus(ECPoint b)
- {
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- return twicePlus(this);
- }
-
- /**
- * Multiplies this <code>ECPoint</code> by the given number.
- * @param k The multiplicator.
- * @return <code>k * this</code>.
- */
- public ECPoint multiply(BigInteger k)
- {
- return this.getCurve().getMultiplier().multiply(this, k);
- }
-
- /**
- * Elliptic curve points over Fp
- */
- public static class Fp extends ECPoint
- {
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- * @param withCompression if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
- public ECFieldElement getZCoord(int index)
- {
- if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
- {
- return getJacobianModifiedW();
- }
-
- return super.getZCoord(index);
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- ECFieldElement X1 = this.x, Y1 = this.y;
- ECFieldElement X2 = b.x, Y2 = b.y;
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
-
- if (dx.isZero())
- {
- if (dy.isZero())
- {
- // this == b, i.e. this must be doubled
- return twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- ECFieldElement gamma = dy.divide(dx);
- ECFieldElement X3 = gamma.square().subtract(X1).subtract(X2);
- ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
-
- return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
- }
-
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Z1 = this.zs[0];
- ECFieldElement Z2 = b.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
- boolean Z2IsOne = Z2.bitLength() == 1;
-
- ECFieldElement u1 = Z1IsOne ? Y2 : Y2.multiply(Z1);
- ECFieldElement u2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
- ECFieldElement u = u1.subtract(u2);
- ECFieldElement v1 = Z1IsOne ? X2 : X2.multiply(Z1);
- ECFieldElement v2 = Z2IsOne ? X1 : X1.multiply(Z2);
- ECFieldElement v = v1.subtract(v2);
-
- // Check if b == this or b == -this
- if (v.isZero())
- {
- if (u.isZero())
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- // TODO Optimize for when w == 1
- ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.multiply(Z2);
- ECFieldElement vSquared = v.square();
- ECFieldElement vCubed = vSquared.multiply(v);
- ECFieldElement vSquaredV2 = vSquared.multiply(v2);
- ECFieldElement A = u.square().multiply(w).subtract(vCubed).subtract(two(vSquaredV2));
-
- ECFieldElement X3 = v.multiply(A);
- ECFieldElement Y3 = vSquaredV2.subtract(A).multiply(u).subtract(vCubed.multiply(u2));
- ECFieldElement Z3 = vCubed.multiply(w);
-
- return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- case ECCurve.COORD_JACOBIAN:
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- ECFieldElement Z1 = this.zs[0];
- ECFieldElement Z2 = b.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
-
- ECFieldElement X3, Y3, Z3, Z3Squared = null;
-
- if (!Z1IsOne && Z1.equals(Z2))
- {
- // TODO Make this available as public method coZAdd?
-
- ECFieldElement dx = X1.subtract(X2), dy = Y1.subtract(Y2);
- if (dx.isZero())
- {
- if (dy.isZero())
- {
- return twice();
- }
- return curve.getInfinity();
- }
-
- ECFieldElement C = dx.square();
- ECFieldElement W1 = X1.multiply(C), W2 = X2.multiply(C);
- ECFieldElement A1 = W1.subtract(W2).multiply(Y1);
-
- X3 = dy.square().subtract(W1).subtract(W2);
- Y3 = W1.subtract(X3).multiply(dy).subtract(A1);
- Z3 = dx;
-
- if (Z1IsOne)
- {
- Z3Squared = C;
- }
- else
- {
- Z3 = Z3.multiply(Z1);
- }
- }
- else
- {
- ECFieldElement Z1Squared, U2, S2;
- if (Z1IsOne)
- {
- Z1Squared = Z1; U2 = X2; S2 = Y2;
- }
- else
- {
- Z1Squared = Z1.square();
- U2 = Z1Squared.multiply(X2);
- ECFieldElement Z1Cubed = Z1Squared.multiply(Z1);
- S2 = Z1Cubed.multiply(Y2);
- }
-
- boolean Z2IsOne = Z2.bitLength() == 1;
- ECFieldElement Z2Squared, U1, S1;
- if (Z2IsOne)
- {
- Z2Squared = Z2; U1 = X1; S1 = Y1;
- }
- else
- {
- Z2Squared = Z2.square();
- U1 = Z2Squared.multiply(X1);
- ECFieldElement Z2Cubed = Z2Squared.multiply(Z2);
- S1 = Z2Cubed.multiply(Y1);
- }
-
- ECFieldElement H = U1.subtract(U2);
- ECFieldElement R = S1.subtract(S2);
-
- // Check if b == this or b == -this
- if (H.isZero())
- {
- if (R.isZero())
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- ECFieldElement HSquared = H.square();
- ECFieldElement G = HSquared.multiply(H);
- ECFieldElement V = HSquared.multiply(U1);
-
- X3 = R.square().add(G).subtract(two(V));
- Y3 = V.subtract(X3).multiply(R).subtract(S1.multiply(G));
-
- Z3 = H;
- if (!Z1IsOne)
- {
- Z3 = Z3.multiply(Z1);
- }
- if (!Z2IsOne)
- {
- Z3 = Z3.multiply(Z2);
- }
-
- // Alternative calculation of Z3 using fast square
- // X3 = four(X3);
- // Y3 = eight(Y3);
- // Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).multiply(H);
-
- if (Z3 == H)
- {
- Z3Squared = HSquared;
- }
- }
-
- ECFieldElement[] zs;
- if (coord == ECCurve.COORD_JACOBIAN_MODIFIED)
- {
- // TODO If the result will only be used in a subsequent addition, we don't need W3
- ECFieldElement W3 = calculateJacobianModifiedW(Z3, Z3Squared);
-
- zs = new ECFieldElement[]{ Z3, W3 };
- }
- else
- {
- zs = new ECFieldElement[]{ Z3 };
- }
-
- return new ECPoint.Fp(curve, X3, Y3, zs, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- int coord = curve.getCoordinateSystem();
-
- ECFieldElement X1 = this.x;
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement X1Squared = X1.square();
- ECFieldElement gamma = three(X1Squared).add(this.getCurve().getA()).divide(two(Y1));
- ECFieldElement X3 = gamma.square().subtract(two(X1));
- ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
-
- return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
- }
-
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
-
- // TODO Optimize for small negative a4 and -3
- ECFieldElement w = curve.getA();
- if (!Z1IsOne)
- {
- w = w.multiply(Z1Squared);
- }
- w = w.add(three(X1.square()));
-
- ECFieldElement s = Z1IsOne ? Y1 : Y1.multiply(Z1);
- ECFieldElement t = Z1IsOne ? Y1.square() : s.multiply(Y1);
- ECFieldElement B = X1.multiply(t);
- ECFieldElement _4B = four(B);
- ECFieldElement h = w.square().subtract(two(_4B));
-
- ECFieldElement X3 = two(h.multiply(s));
- ECFieldElement Y3 = w.multiply(_4B.subtract(h)).subtract(two(two(t).square()));
- ECFieldElement _4sSquared = Z1IsOne ? four(t) : two(s).square();
- ECFieldElement Z3 = two(_4sSquared).multiply(s);
-
- return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- case ECCurve.COORD_JACOBIAN:
- {
- ECFieldElement Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
-
- ECFieldElement Y1Squared = Y1.square();
- ECFieldElement T = Y1Squared.square();
-
- ECFieldElement a4 = curve.getA();
- ECFieldElement a4Neg = a4.negate();
-
- ECFieldElement M, S;
- if (a4Neg.toBigInteger().equals(BigInteger.valueOf(3)))
- {
- M = three(X1.add(Z1Squared).multiply(X1.subtract(Z1Squared)));
- S = four(Y1Squared.multiply(X1));
- }
- else
- {
- ECFieldElement X1Squared = X1.square();
- M = three(X1Squared);
- if (Z1IsOne)
- {
- M = M.add(a4);
- }
- else
- {
- ECFieldElement Z1Pow4 = Z1Squared.square();
- if (a4Neg.bitLength() < a4.bitLength())
- {
- M = M.subtract(Z1Pow4.multiply(a4Neg));
- }
- else
- {
- M = M.add(Z1Pow4.multiply(a4));
- }
- }
- S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
- }
-
- ECFieldElement X3 = M.square().subtract(two(S));
- ECFieldElement Y3 = S.subtract(X3).multiply(M).subtract(eight(T));
-
- ECFieldElement Z3 = two(Y1);
- if (!Z1IsOne)
- {
- Z3 = Z3.multiply(Z1);
- }
-
- // Alternative calculation of Z3 using fast square
-// ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared);
-
- return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- return twiceJacobianModified(true);
- }
-
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement X1 = this.x;
- ECFieldElement X2 = b.x, Y2 = b.y;
-
- ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
-
- if (dx.isZero())
- {
- if (dy.isZero())
- {
- // this == b i.e. the result is 3P
- return threeTimes();
- }
-
- // this == -b, i.e. the result is P
- return this;
- }
-
- /*
- * Optimized calculation of 2P + Q, as described in "Trading Inversions for
- * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
- */
-
- ECFieldElement X = dx.square(), Y = dy.square();
- ECFieldElement d = X.multiply(two(X1).add(X2)).subtract(Y);
- if (d.isZero())
- {
- return curve.getInfinity();
- }
-
- ECFieldElement D = d.multiply(dx);
- ECFieldElement I = D.invert();
- ECFieldElement L1 = d.multiply(I).multiply(dy);
- ECFieldElement L2 = two(Y1).multiply(X).multiply(dx).multiply(I).subtract(L1);
- ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X2);
- ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
-
- return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
- }
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- return twiceJacobianModified(false).add(b);
- }
- default:
- {
- return twice().add(b);
- }
- }
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement X1 = this.x, Y1 = this.y;
-
- ECFieldElement _2Y1 = two(Y1);
- ECFieldElement X = _2Y1.square();
- ECFieldElement Z = three(X1.square()).add(this.getCurve().getA());
- ECFieldElement Y = Z.square();
-
- ECFieldElement d = three(X1).multiply(X).subtract(Y);
- if (d.isZero())
- {
- return this.getCurve().getInfinity();
- }
-
- ECFieldElement D = d.multiply(_2Y1);
- ECFieldElement I = D.invert();
- ECFieldElement L1 = d.multiply(I).multiply(Z);
- ECFieldElement L2 = X.square().multiply(I).subtract(L1);
-
- ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X1);
- ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
- return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
- }
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- return twiceJacobianModified(false).add(this);
- }
- default:
- {
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
- }
- }
-
- protected ECFieldElement two(ECFieldElement x)
- {
- return x.add(x);
- }
-
- protected ECFieldElement three(ECFieldElement x)
- {
- return two(x).add(x);
- }
-
- protected ECFieldElement four(ECFieldElement x)
- {
- return two(two(x));
- }
-
- protected ECFieldElement eight(ECFieldElement x)
- {
- return four(two(x));
- }
-
- protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
- ECFieldElement aSquared, ECFieldElement bSquared)
- {
- /*
- * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
- * way to calculate 2.A.B, if A^2 and B^2 are already known.
- */
- return a.add(b).square().subtract(aSquared).subtract(bSquared);
- }
-
- // D.3.2 pg 102 (see Note:)
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- if (ECCurve.COORD_AFFINE != coord)
- {
- return new ECPoint.Fp(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-
- return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
- }
-
- protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
- {
- if (ZSquared == null)
- {
- ZSquared = Z.square();
- }
-
- ECFieldElement W = ZSquared.square();
- ECFieldElement a4 = this.getCurve().getA();
- ECFieldElement a4Neg = a4.negate();
- if (a4Neg.bitLength() < a4.bitLength())
- {
- W = W.multiply(a4Neg).negate();
- }
- else
- {
- W = W.multiply(a4);
- }
- return W;
- }
-
- protected ECFieldElement getJacobianModifiedW()
- {
- ECFieldElement W = this.zs[1];
- if (W == null)
- {
- // NOTE: Rarely, twicePlus will result in the need for a lazy W1 calculation here
- this.zs[1] = W = calculateJacobianModifiedW(this.zs[0], null);
- }
- return W;
- }
-
- protected ECPoint.Fp twiceJacobianModified(boolean calculateW)
- {
- ECFieldElement X1 = this.x, Y1 = this.y, Z1 = this.zs[0], W1 = getJacobianModifiedW();
-
- ECFieldElement X1Squared = X1.square();
- ECFieldElement M = three(X1Squared).add(W1);
- ECFieldElement Y1Squared = Y1.square();
- ECFieldElement T = Y1Squared.square();
- ECFieldElement S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
- ECFieldElement X3 = M.square().subtract(two(S));
- ECFieldElement _8T = eight(T);
- ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
- ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
- ECFieldElement Z3 = two(Z1.bitLength() == 1 ? Y1 : Y1.multiply(Z1));
-
- return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
- }
- }
-
- /**
- * Elliptic curve points over F2m
- */
- public static class F2m extends ECPoint
- {
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- * @param withCompression true if encode with point compression.
- *
- * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- if (x != null)
- {
- // Check if x and y are elements of the same field
- ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-
- // Check if x and a are elements of the same field
- if (curve != null)
- {
- ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
- }
- }
-
- this.withCompression = withCompression;
-
-// checkCurveEquation();
- }
-
- F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
-
-// checkCurveEquation();
- }
-
- public ECFieldElement getYCoord()
- {
- int coord = this.getCurveCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // TODO The X == 0 stuff needs further thought
- if (this.isInfinity() || x.isZero())
- {
- return y;
- }
-
- // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
- ECFieldElement X = x, L = y;
- ECFieldElement Y = L.subtract(X).multiply(X);
- if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
- {
- ECFieldElement Z = zs[0];
- if (Z.bitLength() != 1)
- {
- Y = Y.divide(Z);
- }
- }
- return Y;
- }
- default:
- {
- return y;
- }
- }
- }
-
- protected boolean getCompressionYTilde()
- {
- ECFieldElement X = this.getRawXCoord();
- if (X.isZero())
- {
- return false;
- }
-
- ECFieldElement Y = this.getRawYCoord();
-
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // Y is actually Lambda (X + Y/X) here
- return Y.subtract(X).testBitZero();
- }
- default:
- {
- return Y.divide(X).testBitZero();
- }
- }
- }
-
- /**
- * Check, if two <code>ECPoint</code>s can be added or subtracted.
- * @param a The first <code>ECPoint</code> to check.
- * @param b The second <code>ECPoint</code> to check.
- * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
- * cannot be added.
- */
- private static void checkPoints(ECPoint a, ECPoint b)
- {
- // Check, if points are on the same curve
- if (a.curve != b.curve)
- {
- throw new IllegalArgumentException("Only points on the same "
- + "curve can be added or subtracted");
- }
-
-// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
- }
-
- /* (non-Javadoc)
- * @see org.spongycastle.math.ec.ECPoint#add(org.spongycastle.math.ec.ECPoint)
- */
- public ECPoint add(ECPoint b)
- {
- checkPoints(this, b);
- return addSimple((ECPoint.F2m)b);
- }
-
- /**
- * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
- * checking if both points are on the same curve. Used by multiplication
- * algorithms, because there all points are a multiple of the same point
- * and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to add to
- * <code>this</code>.
- * @return <code>this + b</code>
- */
- public ECPoint.F2m addSimple(ECPoint.F2m b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- ECFieldElement X1 = this.x;
- ECFieldElement X2 = b.x;
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement Y1 = this.y;
- ECFieldElement Y2 = b.y;
-
- if (X1.equals(X2))
- {
- if (Y1.equals(Y2))
- {
- return (ECPoint.F2m)twice();
- }
-
- return (ECPoint.F2m)curve.getInfinity();
- }
-
- ECFieldElement sumX = X1.add(X2);
- ECFieldElement L = Y1.add(Y2).divide(sumX);
-
- ECFieldElement X3 = L.square().add(L).add(sumX).add(curve.getA());
- ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
-
- return new ECPoint.F2m(curve, X3, Y3, this.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 }, this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- if (X1.isZero())
- {
- return b.addSimple(this);
- }
-
- ECFieldElement L1 = this.y, Z1 = this.zs[0];
- ECFieldElement L2 = b.y, Z2 = b.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement U2 = X2, S2 = L2;
- if (!Z1IsOne)
- {
- U2 = U2.multiply(Z1);
- S2 = S2.multiply(Z1);
- }
-
- boolean Z2IsOne = Z2.bitLength() == 1;
- ECFieldElement U1 = X1, S1 = L1;
- if (!Z2IsOne)
- {
- U1 = U1.multiply(Z2);
- S1 = S1.multiply(Z2);
- }
-
- ECFieldElement A = S1.add(S2);
- ECFieldElement B = U1.add(U2);
-
- if (B.isZero())
- {
- if (A.isZero())
- {
- return (ECPoint.F2m)twice();
- }
-
- return (ECPoint.F2m)curve.getInfinity();
- }
-
- ECFieldElement X3, L3, Z3;
- if (X2.isZero())
- {
- // TODO This can probably be optimized quite a bit
-
- ECFieldElement Y1 = getYCoord(), Y2 = L2;
- ECFieldElement L = Y1.add(Y2).divide(X1);
-
- X3 = L.square().add(L).add(X1).add(curve.getA());
- ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
- L3 = X3.isZero() ? Y3 : Y3.divide(X3).add(X3);
- Z3 = curve.fromBigInteger(ECConstants.ONE);
- }
- else
- {
- B = B.square();
-
- ECFieldElement AU1 = A.multiply(U1);
- ECFieldElement AU2 = A.multiply(U2);
- ECFieldElement ABZ2 = A.multiply(B);
- if (!Z2IsOne)
- {
- ABZ2 = ABZ2.multiply(Z2);
- }
-
- X3 = AU1.multiply(AU2);
- L3 = AU2.add(B).square().add(ABZ2.multiply(L1.add(Z1)));
-
- Z3 = ABZ2;
- if (!Z1IsOne)
- {
- Z3 = Z3.multiply(Z1);
- }
- }
-
- return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- /* (non-Javadoc)
- * @see org.spongycastle.math.ec.ECPoint#subtract(org.spongycastle.math.ec.ECPoint)
- */
- public ECPoint subtract(ECPoint b)
- {
- checkPoints(this, b);
- return subtractSimple((ECPoint.F2m)b);
- }
-
- /**
- * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
- * without checking if both points are on the same curve. Used by
- * multiplication algorithms, because there all points are a multiple
- * of the same point and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to subtract from
- * <code>this</code>.
- * @return <code>this - b</code>
- */
- public ECPoint.F2m subtractSimple(ECPoint.F2m b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return addSimple((ECPoint.F2m)b.negate());
- }
-
- public ECPoint.F2m tau()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.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(), this.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() }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement X1 = this.x;
- if (X1.isZero())
- {
- // A point with X == 0 is it's own additive inverse
- return curve.getInfinity();
- }
-
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement Y1 = this.y;
-
- ECFieldElement L1 = Y1.divide(X1).add(X1);
-
- ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
- ECFieldElement Y3 = X1.square().add(X3.multiply(L1.addOne()));
-
- return new ECPoint.F2m(curve, X3, Y3, this.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 }, this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement L1 = this.y, Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
- ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
- ECFieldElement a = curve.getA();
- ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
- ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
-
- ECFieldElement X3 = T.square();
- ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
-
- ECFieldElement b = curve.getB();
- ECFieldElement L3;
- if (b.bitLength() < (curve.getFieldSize() >> 1))
- {
- ECFieldElement t1 = L1.add(X1).square();
- ECFieldElement t2 = aZ1Sq.square();
- ECFieldElement t3 = curve.getB().multiply(Z1Sq.square());
- L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3));
- }
- else
- {
- ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
- L3 = X1Z1.square().add(X3).add(T.multiply(L1Z1)).add(Z3);
- }
-
- return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement X1 = this.x;
- if (X1.isZero())
- {
- // A point with X == 0 is it's own additive inverse
- return b;
- }
-
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // NOTE: twicePlus() only optimized for lambda-affine argument
- ECFieldElement X2 = b.x, Z2 = b.zs[0];
- if (X2.isZero() || Z2.bitLength() != 1)
- {
- return twice().add(b);
- }
-
- ECFieldElement L1 = this.y, Z1 = this.zs[0];
- ECFieldElement L2 = b.y;
-
- ECFieldElement X1Sq = X1.square();
- ECFieldElement L1Sq = L1.square();
- ECFieldElement Z1Sq = Z1.square();
- ECFieldElement L1Z1 = L1.multiply(Z1);
-
- ECFieldElement T = curve.getA().multiply(Z1Sq).add(L1Sq).add(L1Z1);
- ECFieldElement L2plus1 = L2.addOne();
- ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiply(T).add(X1Sq.multiply(Z1Sq));
- ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
- ECFieldElement B = X2Z1Sq.add(T).square();
-
- ECFieldElement X3 = A.square().multiply(X2Z1Sq);
- ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
- ECFieldElement L3 = A.add(B).square().multiply(T).add(L2plus1.multiply(Z3));
-
- return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- default:
- {
- return twice().add(b);
- }
- }
- }
-
- protected void checkCurveEquation()
- {
- if (this.isInfinity())
- {
- return;
- }
-
- ECFieldElement Z;
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- Z = curve.fromBigInteger(ECConstants.ONE);
- break;
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- Z = this.zs[0];
- break;
- default:
- return;
- }
-
- if (Z.isZero())
- {
- throw new IllegalStateException();
- }
-
- ECFieldElement X = this.x;
- if (X.isZero())
- {
- // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
- ECFieldElement Y = this.y;
- if (!Y.square().equals(curve.getB().multiply(Z)))
- {
- throw new IllegalStateException();
- }
-
- return;
- }
-
- ECFieldElement L = this.y;
- ECFieldElement XSq = X.square();
- ECFieldElement ZSq = Z.square();
-
- ECFieldElement lhs = L.square().add(L.multiply(Z)).add(this.getCurve().getA().multiply(ZSq)).multiply(XSq);
- ECFieldElement rhs = ZSq.square().multiply(this.getCurve().getB()).add(XSq.square());
-
- if (!lhs.equals(rhs))
- {
- throw new IllegalStateException("F2m Lambda-Projective invariant broken");
- }
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECFieldElement X = this.x;
- if (X.isZero())
- {
- return this;
- }
-
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement Y = this.y;
- return new ECPoint.F2m(curve, X, Y.add(X), this.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 }, this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- ECFieldElement L = this.y;
- return new ECPoint.F2m(curve, X, L.addOne(), this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // L is actually Lambda (X + Y/X) here
- ECFieldElement L = this.y, Z = this.zs[0];
- return new ECPoint.F2m(curve, X, L.add(Z), new ECFieldElement[]{ Z }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
- }
-}