Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-07-22 16:23:34 +0400
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-07-22 16:23:34 +0400
commit5cb2f0578e6ec8f0d67e59d05d8c4704d8e05f83 (patch)
tree2919232d66bfd07dec563ecc315c7a7161abfdd6
parent8bfd438251442bfe6e0cdaabe054a3ffc88d794e (diff)
Add automatic EC point validation for decoded points and for multiplier outputs.
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java20
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java8
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java56
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECCurve.java183
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECPoint.java270
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java28
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java17
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java33
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java19
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java19
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java33
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java19
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java18
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java33
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java19
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java18
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java18
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java18
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java33
-rw-r--r--docs/releasenotes.html2
26 files changed, 401 insertions, 637 deletions
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
index 08321494..3405130e 100644
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
+++ b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
@@ -125,7 +125,7 @@ public abstract class DSTU4145PointEncoder
xp = xp.addOne();
}
- ECFieldElement yp;
+ ECFieldElement yp = null;
if (xp.isZero())
{
yp = curve.getB().sqrt();
@@ -134,15 +134,19 @@ public abstract class DSTU4145PointEncoder
{
ECFieldElement beta = xp.square().invert().multiply(curve.getB()).add(curve.getA()).add(xp);
ECFieldElement z = solveQuadraticEquation(curve, beta);
- if (z == null)
+ if (z != null)
{
- throw new RuntimeException("Invalid point compression");
+ if (!trace(z).equals(k))
+ {
+ z = z.addOne();
+ }
+ yp = xp.multiply(z);
}
- if (!trace(z).equals(k))
- {
- z = z.addOne();
- }
- yp = xp.multiply(z);
+ }
+
+ if (yp == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
}
return curve.createPoint(xp.toBigInteger(), yp.toBigInteger());
diff --git a/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
index 69ab7972..d1f35c56 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
@@ -13,7 +13,13 @@ public abstract class AbstractECMultiplier implements ECMultiplier
}
ECPoint positive = multiplyPositive(p, k.abs());
- return sign > 0 ? positive : positive.negate();
+ ECPoint result = sign > 0 ? positive : positive.negate();
+
+ /*
+ * Although the various multipliers ought not to produce invalid output under normal
+ * circumstances, a final check here is advised to guard against fault attacks.
+ */
+ return ECAlgorithms.validatePoint(result);
}
protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
index 2d4a9708..ef208efb 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -52,10 +52,10 @@ public class ECAlgorithms
ECEndomorphism endomorphism = c.getEndomorphism();
if (endomorphism instanceof GLVEndomorphism)
{
- return implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism);
+ return ECAlgorithms.validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
}
- return implSumOfMultiplies(imported, ks);
+ return ECAlgorithms.validatePoint(implSumOfMultiplies(imported, ks));
}
public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
@@ -70,17 +70,18 @@ public class ECAlgorithms
ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
if (f2mCurve.isKoblitz())
{
- return P.multiply(a).add(Q.multiply(b));
+ return ECAlgorithms.validatePoint(P.multiply(a).add(Q.multiply(b)));
}
}
ECEndomorphism endomorphism = cp.getEndomorphism();
if (endomorphism instanceof GLVEndomorphism)
{
- return implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism);
+ return ECAlgorithms.validatePoint(
+ implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism));
}
- return implShamirsTrickWNaf(P, a, Q, b);
+ return ECAlgorithms.validatePoint(implShamirsTrickWNaf(P, a, Q, b));
}
/*
@@ -108,7 +109,7 @@ public class ECAlgorithms
ECCurve cp = P.getCurve();
Q = importPoint(cp, Q);
- return implShamirsTrickJsf(P, k, Q, l);
+ return ECAlgorithms.validatePoint(implShamirsTrickJsf(P, k, Q, l));
}
public static ECPoint importPoint(ECCurve c, ECPoint p)
@@ -152,6 +153,49 @@ public class ECAlgorithms
zs[off] = u;
}
+ /**
+ * Simple shift-and-add multiplication. Serves as reference implementation
+ * to verify (possibly faster) implementations, and for very small scalars.
+ *
+ * @param p
+ * The point to multiply.
+ * @param k
+ * The multiplier.
+ * @return The result of the point multiplication <code>kP</code>.
+ */
+ public static ECPoint referenceMultiply(ECPoint p, BigInteger k)
+ {
+ BigInteger x = k.abs();
+ ECPoint q = p.getCurve().getInfinity();
+ int t = x.bitLength();
+ if (t > 0)
+ {
+ if (x.testBit(0))
+ {
+ q = p;
+ }
+ for (int i = 1; i < t; i++)
+ {
+ p = p.twice();
+ if (x.testBit(i))
+ {
+ q = q.add(p);
+ }
+ }
+ }
+ return k.signum() < 0 ? q.negate() : q;
+ }
+
+ public static ECPoint validatePoint(ECPoint p)
+ {
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point");
+ }
+
+ return p;
+ }
+
static ECPoint implShamirsTrickJsf(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
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 c9a85fe1..9ddbc993 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -105,6 +105,30 @@ public abstract class ECCurve
return new Config(this.coord, this.endomorphism, this.multiplier);
}
+ public ECPoint validatePoint(BigInteger x, BigInteger y)
+ {
+ ECPoint p = createPoint(x, y);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)}
+ * and refer {@link ECPoint#getEncoded(boolean)}
+ */
+ public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ ECPoint p = createPoint(x, y, withCompression);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
+ }
+
public ECPoint createPoint(BigInteger x, BigInteger y)
{
return createPoint(x, y, false);
@@ -190,7 +214,7 @@ public abstract class ECCurve
// TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
p = p.normalize();
- return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
+ return validatePoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
}
/**
@@ -304,7 +328,8 @@ public abstract class ECCurve
ECPoint p = null;
int expectedLength = (getFieldSize() + 7) / 8;
- switch (encoded[0])
+ byte type = encoded[0];
+ switch (type)
{
case 0x00: // infinity
{
@@ -324,7 +349,7 @@ public abstract class ECCurve
throw new IllegalArgumentException("Incorrect length for compressed encoding");
}
- int yTilde = encoded[0] & 1;
+ int yTilde = type & 1;
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
p = decompressPoint(yTilde, X);
@@ -340,7 +365,7 @@ public abstract class ECCurve
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
- p = createPoint(X, Y);
+ p = validatePoint(X, Y);
break;
}
case 0x06: // hybrid
@@ -353,17 +378,22 @@ public abstract class ECCurve
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
-
- if (Y.testBit(0) != (encoded[0] == 0x07))
+
+ if (Y.testBit(0) != (type == 0x07))
{
throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding");
}
- p = createPoint(X, Y);
+ p = validatePoint(X, Y);
break;
}
default:
- throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
+ throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16));
+ }
+
+ if (type != 0x00 && p.isInfinity())
+ {
+ throw new IllegalArgumentException("Invalid infinity encoding");
}
return p;
@@ -415,10 +445,41 @@ public abstract class ECCurve
^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16);
}
+ public static abstract class AbstractFp extends ECCurve
+ {
+ protected AbstractFp(BigInteger q)
+ {
+ super(FiniteFields.getPrimeField(q));
+ }
+
+ protected ECPoint decompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = fromBigInteger(X1);
+ ECFieldElement rhs = x.square().add(a).multiply(x).add(b);
+ ECFieldElement y = rhs.sqrt();
+
+ /*
+ * If y is not a square, then we haven't got a point on the curve
+ */
+ if (y == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ if (y.testBitZero() != (yTilde == 1))
+ {
+ // Use the other root
+ y = y.negate();
+ }
+
+ return createRawPoint(x, y, true);
+ }
+ }
+
/**
* Elliptic curve over Fp
*/
- public static class Fp extends ECCurve
+ public static class Fp extends AbstractFp
{
private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
@@ -432,7 +493,7 @@ public abstract class ECCurve
public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.q = q;
this.r = ECFieldElement.Fp.calculateResidue(q);
@@ -452,7 +513,7 @@ public abstract class ECCurve
protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.q = q;
this.r = r;
@@ -531,44 +592,14 @@ public abstract class ECCurve
return super.importPoint(p);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(a).multiply(x).add(b);
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new ECPoint.Fp(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
}
}
- /**
- * Elliptic curves over F2m. The Weierstrass equation is given by
- * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
- */
- public static class F2m extends ECCurve
+ public static abstract class AbstractF2m extends ECCurve
{
- private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
-
private static FiniteField buildField(int m, int k1, int k2, int k3)
{
if (k1 == 0)
@@ -599,6 +630,20 @@ public abstract class ECCurve
return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
}
+ protected AbstractF2m(int m, int k1, int k2, int k3)
+ {
+ super(buildField(m, k1, k2, k3));
+ }
+ }
+
+ /**
+ * Elliptic curves over F2m. The Weierstrass equation is given by
+ * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
+ */
+ public static class F2m extends AbstractF2m
+ {
+ private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
*/
@@ -763,7 +808,7 @@ public abstract class ECCurve
BigInteger order,
BigInteger cofactor)
{
- super(buildField(m, k1, k2, k3));
+ super(m, k1, k2, k3);
this.m = m;
this.k1 = k1;
@@ -780,7 +825,7 @@ public abstract class ECCurve
protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
{
- super(buildField(m, k1, k2, k3));
+ super(m, k1, k2, k3);
this.m = m;
this.k1 = k1;
@@ -929,7 +974,7 @@ public abstract class ECCurve
*/
protected ECPoint decompressPoint(int yTilde, BigInteger X1)
{
- ECFieldElement xp = fromBigInteger(X1), yp;
+ ECFieldElement xp = fromBigInteger(X1), yp = null;
if (xp.isZero())
{
yp = b.sqrt();
@@ -938,34 +983,38 @@ public abstract class ECCurve
{
ECFieldElement beta = xp.square().invert().multiply(b).add(a).add(xp);
ECFieldElement z = solveQuadraticEquation(beta);
- if (z == null)
+ if (z != null)
{
- throw new IllegalArgumentException("Invalid point compression");
- }
- if (z.testBitZero() != (yTilde == 1))
- {
- z = z.addOne();
- }
+ if (z.testBitZero() != (yTilde == 1))
+ {
+ z = z.addOne();
+ }
- switch (this.getCoordinateSystem())
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- yp = z.add(xp);
- break;
- }
- default:
- {
- yp = z.multiply(xp);
- break;
- }
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ yp = z.add(xp);
+ break;
+ }
+ default:
+ {
+ yp = z.multiply(xp);
+ break;
+ }
+ }
}
}
- return new ECPoint.F2m(this, xp, yp, true);
+ if (yp == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ return createRawPoint(xp, yp, true);
}
-
+
/**
* Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
* D.1.6) The other solution is <code>z + 1</code>.
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 e48244f4..53260179 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -64,6 +64,8 @@ public abstract class ECPoint
this.zs = zs;
}
+ protected abstract boolean satisfiesCurveEquation();
+
public final ECPoint getDetachedPoint()
{
return normalize().detach();
@@ -284,6 +286,33 @@ public abstract class ECPoint
return this.withCompression;
}
+ public boolean isValid()
+ {
+ if (isInfinity())
+ {
+ return true;
+ }
+
+ // TODO Sanity-check the field elements
+
+ ECCurve curve = getCurve();
+ if (curve != null)
+ {
+ if (!satisfiesCurveEquation())
+ {
+ return false;
+ }
+
+ BigInteger h = curve.getCofactor();
+ if (h != null && ECAlgorithms.referenceMultiply(this, h).isInfinity())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public ECPoint scaleX(ECFieldElement scale)
{
return isInfinity()
@@ -482,10 +511,81 @@ public abstract class ECPoint
return this.getCurve().getMultiplier().multiply(this, k);
}
+ public static abstract class AbstractFp extends ECPoint
+ {
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ return this.getAffineYCoord().testBitZero();
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECFieldElement X = this.x, Y = this.y, A = curve.getA(), B = curve.getB();
+ ECFieldElement lhs = Y.square();
+
+ switch (getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z2);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square(), Z6 = Z2.multiply(Z4);
+ A = A.multiply(Z4);
+ B = B.multiply(Z6);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.square().add(A).multiply(X).add(B);
+ return lhs.equals(rhs);
+ }
+
+ public ECPoint subtract(ECPoint b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return add(b.negate());
+ }
+ }
+
/**
* Elliptic curve points over Fp
*/
- public static class Fp extends ECPoint
+ public static class Fp extends AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -502,7 +602,7 @@ public abstract class ECPoint
}
/**
- * Create a point that encodes with or without point compresion.
+ * Create a point that encodes with or without point compression.
*
* @param curve the curve to use
* @param x affine x co-ordinate
@@ -535,11 +635,6 @@ public abstract class ECPoint
return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECFieldElement getZCoord(int index)
{
if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
@@ -1162,18 +1257,6 @@ public abstract class ECPoint
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())
@@ -1249,10 +1332,91 @@ public abstract class ECPoint
}
}
+ public static abstract class AbstractF2m extends ECPoint
+ {
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECCurve curve = getCurve();
+ ECFieldElement X = this.x, A = curve.getA(), B = curve.getB();
+
+ int coord = curve.getCoordinateSystem();
+ if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE)
+ {
+ ECFieldElement Z = this.zs[0];
+ boolean ZIsOne = Z.isOne();
+
+ if (X.isZero())
+ {
+ // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.square(), rhs = B;
+ if (!ZIsOne)
+ {
+ rhs = rhs.multiply(Z.square());
+ }
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement L = this.y, X2 = X.square();
+ ECFieldElement lhs, rhs;
+ if (ZIsOne)
+ {
+ lhs = L.square().add(L).add(A);
+ rhs = X2.square().add(B);
+ }
+ else
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square();
+ lhs = L.add(Z).multiplyPlusProduct(L, A, Z2);
+ // TODO If sqrt(b) is precomputed this can be simplified to a single square
+ rhs = X2.squarePlusProduct(B, Z4);
+ }
+ lhs = lhs.multiply(X2);
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.add(X).multiply(Y);
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.add(A).multiply(X.square()).add(B);
+ return lhs.equals(rhs);
+ }
+ }
+
/**
* Elliptic curve points over F2m
*/
- public static class F2m extends ECPoint
+ public static class F2m extends AbstractF2m
{
/**
* @param curve base curve
@@ -1907,72 +2071,6 @@ public abstract class ECPoint
}
}
- 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();
- }
-
- ECCurve curve = this.getCurve();
-
- boolean ZIsOne = Z.isOne();
- ECFieldElement ZSq = ZIsOne ? Z : Z.square();
-
- 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(ZSq)))
- {
- throw new IllegalStateException();
- }
-
- return;
- }
-
- ECFieldElement A = curve.getA(), B = curve.getB();
- ECFieldElement L = this.y;
- ECFieldElement XSq = X.square();
-
- ECFieldElement lhs, rhs;
- if (ZIsOne)
- {
- lhs = L.square().add(L).add(A).multiply(XSq);
- rhs = XSq.square().add(B);
- }
- else
- {
- lhs = L.add(Z).multiplyPlusProduct(L, A, ZSq).multiply(XSq);
- // TODO If sqrt(b) is precomputed this can be simplified to a single square
- rhs = XSq.squarePlusProduct(B, ZSq.square());
- }
-
- if (!lhs.equals(rhs))
- {
- throw new IllegalStateException("F2m Lambda-Projective invariant broken");
- }
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
index 3601856c..107e1937 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
@@ -4,34 +4,8 @@ import java.math.BigInteger;
public class ReferenceMultiplier extends AbstractECMultiplier
{
- /**
- * Simple shift-and-add multiplication. Serves as reference implementation
- * to verify (possibly faster) implementations in
- * {@link org.bouncycastle.math.ec.ECPoint ECPoint}.
- *
- * @param p The point to multiply.
- * @param k The factor by which to multiply.
- * @return The result of the point multiplication <code>k * p</code>.
- */
protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
{
- ECPoint q = p.getCurve().getInfinity();
- int t = k.bitLength();
- if (t > 0)
- {
- if (k.testBit(0))
- {
- q = p;
- }
- for (int i = 1; i < t; i++)
- {
- p = p.twice();
- if (k.testBit(i))
- {
- q = q.add(p);
- }
- }
- }
- return q;
+ return ECAlgorithms.referenceMultiply(p, k);
}
}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java
index 2b201926..e7839ce2 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java
@@ -5,11 +5,10 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.math.raw.Nat256;
import org.bouncycastle.util.encoders.Hex;
-public class Curve25519 extends ECCurve
+public class Curve25519 extends ECCurve.AbstractFp
{
public static final BigInteger q = Nat256.toBigInteger(Curve25519Field.P);
@@ -19,7 +18,7 @@ public class Curve25519 extends ECCurve
public Curve25519()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new Curve25519Point(this, null, null);
@@ -74,30 +73,6 @@ public class Curve25519 extends ECCurve
return new Curve25519Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new Curve25519Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java
index 2a558a61..b2700e30 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java
@@ -5,7 +5,7 @@ import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat256;
-public class Curve25519Point extends ECPoint
+public class Curve25519Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -55,11 +55,6 @@ public class Curve25519Point extends ECPoint
return new Curve25519Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECFieldElement getZCoord(int index)
{
if (index == 1)
@@ -257,16 +252,6 @@ public class Curve25519Point extends ECPoint
return twiceJacobianModified(false).add(this);
}
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- return add(b.negate());
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
index 87d9f10c..b46cba6a 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
@@ -5,15 +5,10 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.GLVMultiplier;
-import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP192K1Curve extends ECCurve
+public class SecP192K1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
@@ -24,7 +19,7 @@ public class SecP192K1Curve extends ECCurve
public SecP192K1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP192K1Point(this, null, null);
@@ -77,30 +72,6 @@ public class SecP192K1Curve extends ECCurve
return new SecP192K1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP192K1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
index f27b994b..eaa97277 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat192;
-public class SecP192K1Point extends ECPoint
+public class SecP192K1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -65,11 +65,6 @@ public class SecP192K1Point extends ECPoint
return new SecP192K1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
// B.3 pg 62
public ECPoint add(ECPoint b)
{
@@ -291,18 +286,6 @@ public class SecP192K1Point extends ECPoint
return twice().add(this);
}
- // 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())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
index 5491609b..be67100a 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
@@ -5,10 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP192R1Curve extends ECCurve
+public class SecP192R1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
@@ -19,7 +18,7 @@ public class SecP192R1Curve extends ECCurve
public SecP192R1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP192R1Point(this, null, null);
@@ -74,30 +73,6 @@ public class SecP192R1Curve extends ECCurve
return new SecP192R1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP192R1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
index 9fa0536a..3ed72f85 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat192;
-public class SecP192R1Point extends ECPoint
+public class SecP192R1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -64,11 +64,6 @@ public class SecP192R1Point extends ECPoint
return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
// B.3 pg 62
public ECPoint add(ECPoint b)
{
@@ -303,18 +298,6 @@ public class SecP192R1Point extends ECPoint
return twice().add(this);
}
- // 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())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
index 8323de1d..ad733da6 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
@@ -5,15 +5,10 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.GLVMultiplier;
-import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP224K1Curve extends ECCurve
+public class SecP224K1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
@@ -24,7 +19,7 @@ public class SecP224K1Curve extends ECCurve
public SecP224K1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP224K1Point(this, null, null);
@@ -76,30 +71,6 @@ public class SecP224K1Curve extends ECCurve
return new SecP224K1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP224K1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
index 9c955605..114623dc 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat224;
-public class SecP224K1Point extends ECPoint
+public class SecP224K1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -65,11 +65,6 @@ public class SecP224K1Point extends ECPoint
return new SecP224K1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
// B.3 pg 62
public ECPoint add(ECPoint b)
{
@@ -291,18 +286,6 @@ public class SecP224K1Point extends ECPoint
return twice().add(this);
}
- // 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())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
index bbb02701..c8443299 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
@@ -5,10 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP224R1Curve extends ECCurve
+public class SecP224R1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
@@ -19,7 +18,7 @@ public class SecP224R1Curve extends ECCurve
public SecP224R1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP224R1Point(this, null, null);
@@ -74,30 +73,6 @@ public class SecP224R1Curve extends ECCurve
return new SecP224R1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP224R1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
index c170f997..df10b9b4 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat224;
-public class SecP224R1Point extends ECPoint
+public class SecP224R1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -64,11 +64,6 @@ public class SecP224R1Point extends ECPoint
return new SecP224R1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECPoint add(ECPoint b)
{
if (this.isInfinity())
@@ -301,17 +296,6 @@ public class SecP224R1Point extends ECPoint
return twice().add(this);
}
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
index 7977d9df..9b885764 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
@@ -5,15 +5,10 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.GLVMultiplier;
-import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP256K1Curve extends ECCurve
+public class SecP256K1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
@@ -24,7 +19,7 @@ public class SecP256K1Curve extends ECCurve
public SecP256K1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP256K1Point(this, null, null);
@@ -76,30 +71,6 @@ public class SecP256K1Curve extends ECCurve
return new SecP256K1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP256K1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
index fff74974..f57b200a 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat256;
-public class SecP256K1Point extends ECPoint
+public class SecP256K1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -65,11 +65,6 @@ public class SecP256K1Point extends ECPoint
return new SecP256K1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
// B.3 pg 62
public ECPoint add(ECPoint b)
{
@@ -291,18 +286,6 @@ public class SecP256K1Point extends ECPoint
return twice().add(this);
}
- // 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())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
index ae3bfacb..5ff6a38d 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
@@ -5,10 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP256R1Curve extends ECCurve
+public class SecP256R1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
@@ -19,7 +18,7 @@ public class SecP256R1Curve extends ECCurve
public SecP256R1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP256R1Point(this, null, null);
@@ -74,30 +73,6 @@ public class SecP256R1Curve extends ECCurve
return new SecP256R1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP256R1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
index 09ff15c1..930fdc58 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat256;
-public class SecP256R1Point extends ECPoint
+public class SecP256R1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -64,11 +64,6 @@ public class SecP256R1Point extends ECPoint
return new SecP256R1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECPoint add(ECPoint b)
{
if (this.isInfinity())
@@ -301,17 +296,6 @@ public class SecP256R1Point extends ECPoint
return twice().add(this);
}
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
index ad37b0cd..27cbcdb2 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
@@ -5,10 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP384R1Curve extends ECCurve
+public class SecP384R1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
@@ -19,7 +18,7 @@ public class SecP384R1Curve extends ECCurve
public SecP384R1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP384R1Point(this, null, null);
@@ -74,30 +73,6 @@ public class SecP384R1Curve extends ECCurve
return new SecP384R1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP384R1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
index b18a029e..89f6bf4f 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
@@ -6,7 +6,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat384;
-public class SecP384R1Point extends ECPoint
+public class SecP384R1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -64,11 +64,6 @@ public class SecP384R1Point extends ECPoint
return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECPoint add(ECPoint b)
{
if (this.isInfinity())
@@ -302,17 +297,6 @@ public class SecP384R1Point extends ECPoint
return twice().add(this);
}
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
index ea42b578..16691b10 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
@@ -5,10 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.encoders.Hex;
-public class SecP521R1Curve extends ECCurve
+public class SecP521R1Curve extends ECCurve.AbstractFp
{
public static final BigInteger q = new BigInteger(1,
Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
@@ -19,7 +18,7 @@ public class SecP521R1Curve extends ECCurve
public SecP521R1Curve()
{
- super(FiniteFields.getPrimeField(q));
+ super(q);
this.infinity = new SecP521R1Point(this, null, null);
@@ -74,30 +73,6 @@ public class SecP521R1Curve extends ECCurve
return new SecP521R1Point(this, x, y, zs, withCompression);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.square().add(getA()).multiply(x).add(getB());
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- if (beta.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- beta = beta.negate();
- }
-
- return new SecP521R1Point(this, x, beta, true);
- }
-
public ECPoint getInfinity()
{
return infinity;
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
index 11bbbfc0..d9737152 100644
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
+++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
@@ -5,7 +5,7 @@ import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.raw.Nat;
-public class SecP521R1Point extends ECPoint
+public class SecP521R1Point extends ECPoint.AbstractFp
{
/**
* Create a point which encodes with point compression.
@@ -63,11 +63,6 @@ public class SecP521R1Point extends ECPoint
return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord());
}
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
public ECPoint add(ECPoint b)
{
if (this.isInfinity())
@@ -326,17 +321,6 @@ public class SecP521R1Point extends ECPoint
return a.add(b).square().subtract(aSquared).subtract(bSquared);
}
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java
index 1ad4d760..efd6aca0 100644
--- a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java
+++ b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java
@@ -286,35 +286,6 @@ public class ECPointTest extends TestCase
}
/**
- * Simple shift-and-add multiplication. Serves as reference implementation
- * to verify (possibly faster) implementations in
- * {@link org.bouncycastle.math.ec.ECPoint ECPoint}.
- *
- * @param p
- * The point to multiply.
- * @param k
- * The multiplier.
- * @return The result of the point multiplication <code>kP</code>.
- */
- private ECPoint multiply(ECPoint p, BigInteger k)
- {
- ECPoint q = p.getCurve().getInfinity();
- int t = k.bitLength();
- for (int i = 0; i < t; i++)
- {
- if (i != 0)
- {
- p = p.twice();
- }
- if (k.testBit(i))
- {
- q = q.add(p);
- }
- }
- return q;
- }
-
- /**
* Checks, if the point multiplication algorithm of the given point yields
* the same result as point multiplication done by the reference
* implementation given in <code>multiply()</code>. This method chooses a
@@ -329,7 +300,7 @@ public class ECPointTest extends TestCase
private void implTestMultiply(ECPoint p, int numBits)
{
BigInteger k = new BigInteger(numBits, secRand);
- ECPoint ref = multiply(p, k);
+ ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
ECPoint q = p.multiply(k);
assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
}
@@ -353,7 +324,7 @@ public class ECPointTest extends TestCase
do
{
- ECPoint ref = multiply(p, k);
+ ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
ECPoint q = p.multiply(k);
assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
k = k.add(BigInteger.ONE);
diff --git a/docs/releasenotes.html b/docs/releasenotes.html
index 58ee3900..5384f9f6 100644
--- a/docs/releasenotes.html
+++ b/docs/releasenotes.html
@@ -34,6 +34,7 @@ Release 1.51
<li>User Attribute subpackets in PGP with long length encodings could result in certification verification failing. This has been fixed.</li>
<li>Calls to CommandMap.setDefaultCommandMap() in the SMIME API are now wrapped in doPrivileged() blocks to allow them to work with a security manager.</li>
<li>The encoding of the certificate_authorities field of a TLS CertificateRequest has been fixed.</li>
+<li>EC point formats are now strictly enforced in the TLS API.</li>
</ul>
<h3>2.1.3 Additional Features and Functionality</h3>
<ul>
@@ -44,6 +45,7 @@ Release 1.51
<li>The PGP API now provides automatic conversion of embedded signatures in signature sub-packet vectors.</li>
<li>GCM and GMAC now support tag lengths down to 32 bits.</li>
<li>Custom implementations for many of the SEC Fp curves have been added, resulting in drastically improved performance. The current list includes all secp***k1 and secp***r1 curves from 192 to 521 bits. They can be accessed via the org.bouncycastle.crypto.ec.CustomNamedCurves class and are generally selected by other internal APIs in place of the generic implementations.</li>
+<li>Automatic EC point validation added, both for decoded inputs and multiplier outputs.</li>
</ul>
<h3>2.1.4 Notes</h3>
<ul>