diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-22 16:23:34 +0400 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-22 16:23:34 +0400 |
commit | 5cb2f0578e6ec8f0d67e59d05d8c4704d8e05f83 (patch) | |
tree | 2919232d66bfd07dec563ecc315c7a7161abfdd6 | |
parent | 8bfd438251442bfe6e0cdaabe054a3ffc88d794e (diff) |
Add automatic EC point validation for decoded points and for multiplier outputs.
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> |