diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-23 15:17:12 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-07-23 15:17:12 +0700 |
commit | 6e306046568f9a4d13639b913f0ff6d5879fa165 (patch) | |
tree | 994b8711674bb146ff578c1f0dff649282962acb /crypto | |
parent | Update encrypt_then_mac entry (diff) | |
download | BouncyCastle.NET-ed25519-6e306046568f9a4d13639b913f0ff6d5879fa165.tar.xz |
Add automatic EC point validation for decoded points and for multiplier outputs
Diffstat (limited to 'crypto')
24 files changed, 375 insertions, 494 deletions
diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs index d82cafedf..3c911b173 100644 --- a/crypto/src/math/ec/ECAlgorithms.cs +++ b/crypto/src/math/ec/ECAlgorithms.cs @@ -49,10 +49,10 @@ namespace Org.BouncyCastle.Math.EC GlvEndomorphism glvEndomorphism = c.GetEndomorphism() as GlvEndomorphism; if (glvEndomorphism != null) { - return ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism); + return ValidatePoint(ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism)); } - return ImplSumOfMultiplies(imported, ks); + return ValidatePoint(ImplSumOfMultiplies(imported, ks)); } public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b) @@ -66,17 +66,18 @@ namespace Org.BouncyCastle.Math.EC F2mCurve f2mCurve = (F2mCurve) cp; if (f2mCurve.IsKoblitz) { - return P.Multiply(a).Add(Q.Multiply(b)); + return ValidatePoint(P.Multiply(a).Add(Q.Multiply(b))); } } GlvEndomorphism glvEndomorphism = cp.GetEndomorphism() as GlvEndomorphism; if (glvEndomorphism != null) { - return ImplSumOfMultipliesGlv(new ECPoint[] { P, Q }, new BigInteger[] { a, b }, glvEndomorphism); + return ValidatePoint( + ImplSumOfMultipliesGlv(new ECPoint[] { P, Q }, new BigInteger[] { a, b }, glvEndomorphism)); } - return ImplShamirsTrickWNaf(P, a, Q, b); + return ValidatePoint(ImplShamirsTrickWNaf(P, a, Q, b)); } /* @@ -102,7 +103,7 @@ namespace Org.BouncyCastle.Math.EC ECCurve cp = P.Curve; Q = ImportPoint(cp, Q); - return ImplShamirsTrickJsf(P, k, Q, l); + return ValidatePoint(ImplShamirsTrickJsf(P, k, Q, l)); } public static ECPoint ImportPoint(ECCurve c, ECPoint p) @@ -145,6 +146,47 @@ namespace Org.BouncyCastle.Math.EC 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.Curve.Infinity; + 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.SignValue < 0 ? q.Negate() : q; + } + + public static ECPoint ValidatePoint(ECPoint p) + { + if (!p.IsValid()) + throw new ArgumentException("Invalid point", "p"); + + return p; + } + internal static ECPoint ImplShamirsTrickJsf(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) { ECCurve curve = P.Curve; diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs index 9c16375e6..889da292f 100644 --- a/crypto/src/math/ec/ECCurve.cs +++ b/crypto/src/math/ec/ECCurve.cs @@ -102,6 +102,27 @@ namespace Org.BouncyCastle.Math.EC return new Config(this, this.m_coord, this.m_endomorphism, this.m_multiplier); } + public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y) + { + ECPoint p = CreatePoint(x, y); + if (!p.IsValid()) + { + throw new ArgumentException("Invalid point coordinates"); + } + return p; + } + + [Obsolete("Per-point compression property will be removed")] + public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y, bool withCompression) + { + ECPoint p = CreatePoint(x, y, withCompression); + if (!p.IsValid()) + { + throw new ArgumentException("Invalid point coordinates"); + } + return p; + } + public virtual ECPoint CreatePoint(BigInteger x, BigInteger y) { return CreatePoint(x, y, false); @@ -185,7 +206,7 @@ namespace Org.BouncyCastle.Math.EC // 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.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed); + return ValidatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed); } /** @@ -344,7 +365,8 @@ namespace Org.BouncyCastle.Math.EC ECPoint p = null; int expectedLength = (FieldSize + 7) / 8; - switch (encoded[0]) + byte type = encoded[0]; + switch (type) { case 0x00: // infinity { @@ -361,7 +383,7 @@ namespace Org.BouncyCastle.Math.EC if (encoded.Length != (expectedLength + 1)) throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); - int yTilde = encoded[0] & 1; + int yTilde = type & 1; BigInteger X = new BigInteger(1, encoded, 1, expectedLength); p = DecompressPoint(yTilde, X); @@ -376,7 +398,7 @@ namespace Org.BouncyCastle.Math.EC BigInteger X = new BigInteger(1, encoded, 1, expectedLength); BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); - p = CreatePoint(X, Y); + p = ValidatePoint(X, Y); break; } @@ -389,26 +411,59 @@ namespace Org.BouncyCastle.Math.EC BigInteger X = new BigInteger(1, encoded, 1, expectedLength); BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); - if (Y.TestBit(0) != (encoded[0] == 0x07)) + if (Y.TestBit(0) != (type == 0x07)) throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded"); - p = CreatePoint(X, Y); + p = ValidatePoint(X, Y); break; } default: - throw new FormatException("Invalid point encoding " + encoded[0]); + throw new FormatException("Invalid point encoding " + type); } + if (type != 0x00 && p.IsInfinity) + throw new ArgumentException("Invalid infinity encoding", "encoded"); + return p; } } + public abstract class AbstractFpCurve + : ECCurve + { + protected AbstractFpCurve(BigInteger q) + : base(FiniteFields.GetPrimeField(q)) + { + } + + protected override 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 ArgumentException("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 class FpCurve - : ECCurve + : AbstractFpCurve { private const int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; @@ -421,7 +476,7 @@ namespace Org.BouncyCastle.Math.EC } public FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor) - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_q = q; this.m_r = FpFieldElement.CalculateResidue(q); @@ -440,7 +495,7 @@ namespace Org.BouncyCastle.Math.EC } protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_q = q; this.m_r = r; @@ -523,38 +578,11 @@ namespace Org.BouncyCastle.Math.EC return base.ImportPoint(p); } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = FromBigInteger(X1); - ECFieldElement alpha = x.Square().Add(m_a).Multiply(x).Add(m_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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new FpPoint(this, x, beta, true); - } } - /** - * 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 class F2mCurve : ECCurve + public abstract class AbstractF2mCurve + : ECCurve { - private const int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; - private static IFiniteField BuildField(int m, int k1, int k2, int k3) { if (k1 == 0) @@ -585,6 +613,21 @@ namespace Org.BouncyCastle.Math.EC return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, k2, k3, m }); } + protected AbstractF2mCurve(int m, int k1, int k2, int k3) + : base(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 class F2mCurve + : AbstractF2mCurve + { + private const int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + /** * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. */ @@ -748,7 +791,7 @@ namespace Org.BouncyCastle.Math.EC BigInteger b, BigInteger order, BigInteger cofactor) - : base(BuildField(m, k1, k2, k3)) + : base(m, k1, k2, k3) { this.m = m; this.k1 = k1; @@ -781,7 +824,7 @@ namespace Org.BouncyCastle.Math.EC } protected F2mCurve(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) - : base(BuildField(m, k1, k2, k3)) + : base(m, k1, k2, k3) { this.m = m; this.k1 = k1; @@ -936,7 +979,7 @@ namespace Org.BouncyCastle.Math.EC protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) { - ECFieldElement xp = FromBigInteger(X1), yp; + ECFieldElement xp = FromBigInteger(X1), yp = null; if (xp.IsZero) { yp = m_b.Sqrt(); @@ -946,31 +989,34 @@ namespace Org.BouncyCastle.Math.EC ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp); ECFieldElement z = SolveQuadradicEquation(beta); - if (z == null) - throw new ArithmeticException("Invalid point compression"); - - if (z.TestBitZero() != (yTilde == 1)) - { - z = z.AddOne(); - } - - switch (this.CoordinateSystem) + if (z != null) { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: + if (z.TestBitZero() != (yTilde == 1)) { - yp = z.Add(xp); - break; + z = z.AddOne(); } - default: + + switch (this.CoordinateSystem) { - yp = z.Multiply(xp); - break; + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + yp = z.Add(xp); + break; + } + default: + { + yp = z.Multiply(xp); + break; + } } } } - return new F2mPoint(this, xp, yp, true); + if (yp == null) + throw new ArgumentException("Invalid point compression"); + + return CreateRawPoint(xp, yp, true); } /** diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs index 0430a6110..dbeaf31aa 100644 --- a/crypto/src/math/ec/ECPoint.cs +++ b/crypto/src/math/ec/ECPoint.cs @@ -67,6 +67,8 @@ namespace Org.BouncyCastle.Math.EC this.m_withCompression = withCompression; } + protected abstract bool SatisfiesCurveEquation(); + public ECPoint GetDetachedPoint() { return Normalize().Detach(); @@ -289,6 +291,30 @@ namespace Org.BouncyCastle.Math.EC get { return m_withCompression; } } + public bool IsValid() + { + if (IsInfinity) + return true; + + // TODO Sanity-check the field elements + + ECCurve curve = Curve; + if (curve != null) + { + if (!SatisfiesCurveEquation()) + return false; + + BigInteger h = curve.Cofactor; + if (h != null && !h.Equals(BigInteger.One) + && ECAlgorithms.ReferenceMultiply(this, h).IsInfinity) + { + return false; + } + } + + return true; + } + public virtual ECPoint ScaleX(ECFieldElement scale) { return IsInfinity @@ -497,14 +523,84 @@ namespace Org.BouncyCastle.Math.EC } } + public abstract class AbstractFpPoint + : ECPointBase + { + protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + } + + protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected internal override bool CompressionYTilde + { + get { return this.AffineYCoord.TestBitZero(); } + } + + protected override bool SatisfiesCurveEquation() + { + ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = Curve.A, B = Curve.B; + ECFieldElement lhs = Y.Square(); + + switch (CurveCoordinateSystem) + { + case ECCurve.COORD_AFFINE: + break; + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z = this.RawZCoords[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.RawZCoords[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 InvalidOperationException("unsupported coordinate system"); + } + + ECFieldElement rhs = X.Square().Add(A).Multiply(X).Add(B); + return lhs.Equals(rhs); + } + + public override ECPoint Subtract(ECPoint b) + { + if (b.IsInfinity) + return this; + + // Add -b + return Add(b.Negate()); + } + } + /** * Elliptic curve points over Fp */ public class FpPoint - : ECPointBase + : AbstractFpPoint { /** - * Create a point which encodes with point compression. + * Create a point which encodes without point compression. * * @param curve the curve to use * @param x affine x co-ordinate @@ -516,7 +612,7 @@ namespace Org.BouncyCastle.Math.EC } /** - * 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 @@ -540,11 +636,6 @@ namespace Org.BouncyCastle.Math.EC return new FpPoint(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECFieldElement GetZCoord(int index) { if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.CurveCoordinateSystem) @@ -1135,16 +1226,6 @@ namespace Org.BouncyCastle.Math.EC return a.Add(b).Square().Subtract(aSquared).Subtract(bSquared); } - public override ECPoint Subtract( - ECPoint b) - { - if (b.IsInfinity) - return this; - - // Add -b - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) @@ -1217,11 +1298,96 @@ namespace Org.BouncyCastle.Math.EC } } + public abstract class AbstractF2mPoint + : ECPointBase + { + protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + } + + protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override bool SatisfiesCurveEquation() + { + ECCurve curve = Curve; + ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = curve.A, B = curve.B; + ECFieldElement lhs, rhs; + + int coord = curve.CoordinateSystem; + if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE) + { + ECFieldElement Z = this.RawZCoords[0]; + bool ZIsOne = Z.IsOne; + + if (X.IsZero) + { + // NOTE: For x == 0, we expect the affine-y instead of the lambda-y + lhs = Y.Square(); + rhs = B; + if (!ZIsOne) + { + ECFieldElement Z2 = Z.Square(); + rhs = rhs.Multiply(Z2); + } + } + else + { + ECFieldElement L = Y, X2 = X.Square(); + 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); + } + } + else + { + lhs = Y.Add(X).Multiply(Y); + + switch (coord) + { + case ECCurve.COORD_AFFINE: + break; + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z = this.RawZCoords[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 InvalidOperationException("unsupported coordinate system"); + } + + rhs = X.Add(A).Multiply(X.Square()).Add(B); + } + + return lhs.Equals(rhs); + } + } + /** * Elliptic curve points over F2m */ public class F2mPoint - : ECPointBase + : AbstractF2mPoint { /** * @param curve base curve diff --git a/crypto/src/math/ec/custom/djb/Curve25519.cs b/crypto/src/math/ec/custom/djb/Curve25519.cs index 3dbdac051..712b68f29 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519.cs @@ -1,13 +1,12 @@ using System; using Org.BouncyCastle.Math.EC.Custom.Sec; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Djb { internal class Curve25519 - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = Nat256.ToBigInteger(Curve25519Field.P); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb protected readonly Curve25519Point m_infinity; public Curve25519() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new Curve25519Point(this, null, null); @@ -74,27 +73,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb { return new Curve25519Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new Curve25519Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/djb/Curve25519Point.cs b/crypto/src/math/ec/custom/djb/Curve25519Point.cs index f3da59d16..bfec1d11d 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519Point.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519Point.cs @@ -5,7 +5,7 @@ using Org.BouncyCastle.Math.EC.Custom.Sec; namespace Org.BouncyCastle.Math.EC.Custom.Djb { internal class Curve25519Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -48,11 +48,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb return new Curve25519Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECFieldElement GetZCoord(int index) { if (index == 1) @@ -224,14 +219,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Djb return TwiceJacobianModified(false).Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs index 54b87588b..81f77197e 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192K1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP192K1Point m_infinity; public SecP192K1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP192K1Point(this, null, null); @@ -72,27 +71,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP192K1Point(this, x, y, zs, withCompression); } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = FromBigInteger(X1); - ECFieldElement alpha = x.Square().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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP192K1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs index 561324f8e..648aca502 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192K1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -55,11 +55,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP192K1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -259,14 +254,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs index 57b20d31e..cb3a981c8 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192R1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP192R1Point m_infinity; public SecP192R1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP192R1Point(this, null, null); @@ -75,27 +74,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP192R1Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP192R1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs index c249c1269..797a8de35 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192R1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -54,11 +54,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP192R1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -271,14 +266,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs index 70de308bb..d4be7d8de 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224K1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP224K1Point m_infinity; public SecP224K1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP224K1Point(this, null, null); @@ -72,27 +71,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP224K1Point(this, x, y, zs, withCompression); } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = FromBigInteger(X1); - ECFieldElement alpha = x.Square().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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP224K1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs index dd6faa829..8cbd29699 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224K1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -55,11 +55,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP224K1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -259,14 +254,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs index 33b66be82..cda8781ff 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224R1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP224R1Point m_infinity; public SecP224R1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP224R1Point(this, null, null); @@ -75,27 +74,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP224R1Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP224R1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs index 3b339720d..c3f4efb59 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224R1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -54,11 +54,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP224R1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -271,14 +266,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs index 89de61706..59e2cefb2 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256K1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP256K1Point m_infinity; public SecP256K1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP256K1Point(this, null, null); @@ -72,27 +71,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP256K1Point(this, x, y, zs, withCompression); } - - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = FromBigInteger(X1); - ECFieldElement alpha = x.Square().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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP256K1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs index b12eadb72..3165682fa 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256K1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -55,11 +55,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP256K1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -259,14 +254,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs index 9a94eb8d1..6b3448f06 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256R1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP256R1Point m_infinity; public SecP256R1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP256R1Point(this, null, null); @@ -74,27 +73,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP256R1Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP256R1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs index 0e4b95a10..1de4a0b4a 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256R1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -54,11 +54,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP256R1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -271,14 +266,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs index f3dec05c9..7fd58276a 100644 --- a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP384R1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP384R1Point m_infinity; public SecP384R1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP384R1Point(this, null, null); @@ -74,27 +73,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP384R1Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP384R1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Point.cs b/crypto/src/math/ec/custom/sec/SecP384R1Point.cs index 1ca8489dc..68c601611 100644 --- a/crypto/src/math/ec/custom/sec/SecP384R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP384R1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP384R1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -54,11 +54,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP384R1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -272,14 +267,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs index cb42304ef..e5083c7f0 100644 --- a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs +++ b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs @@ -1,12 +1,11 @@ using System; -using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP521R1Curve - : ECCurve + : AbstractFpCurve { public static readonly BigInteger q = new BigInteger(1, Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); @@ -16,7 +15,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected readonly SecP521R1Point m_infinity; public SecP521R1Curve() - : base(FiniteFields.GetPrimeField(q)) + : base(q) { this.m_infinity = new SecP521R1Point(this, null, null); @@ -74,27 +73,5 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { return new SecP521R1Point(this, x, y, zs, withCompression); } - - protected override 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 ArithmeticException("Invalid point compression"); - - if (beta.TestBitZero() != (yTilde == 1)) - { - // Use the other root - beta = beta.Negate(); - } - - return new SecP521R1Point(this, x, beta, true); - } } } diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Point.cs b/crypto/src/math/ec/custom/sec/SecP521R1Point.cs index 44d590f08..fb1996cfd 100644 --- a/crypto/src/math/ec/custom/sec/SecP521R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP521R1Point.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP521R1Point - : ECPointBase + : AbstractFpPoint { /** * Create a point which encodes with point compression. @@ -54,11 +54,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return new SecP521R1Point(null, AffineXCoord, AffineYCoord); } - protected internal override bool CompressionYTilde - { - get { return this.AffineYCoord.TestBitZero(); } - } - public override ECPoint Add(ECPoint b) { if (this.IsInfinity) @@ -267,14 +262,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return Twice().Add(this); } - public override ECPoint Subtract(ECPoint b) - { - if (b.IsInfinity) - return this; - - return Add(b.Negate()); - } - public override ECPoint Negate() { if (IsInfinity) diff --git a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs index fe683726f..517881323 100644 --- a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs +++ b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs @@ -10,7 +10,13 @@ return p.Curve.Infinity; 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/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs index 832fd7be4..4848ada39 100644 --- a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs +++ b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs @@ -3,35 +3,9 @@ namespace Org.BouncyCastle.Math.EC.Multiplier public class ReferenceMultiplier : 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 override ECPoint MultiplyPositive(ECPoint p, BigInteger k) { - ECPoint q = p.Curve.Infinity; - 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/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs index 1a23e0bc7..8430f437d 100644 --- a/crypto/test/src/math/ec/test/ECPointTest.cs +++ b/crypto/test/src/math/ec/test/ECPointTest.cs @@ -288,35 +288,6 @@ namespace Org.BouncyCastle.Math.EC.Tests } /** - * 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.Curve.Infinity; - 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 @@ -331,7 +302,7 @@ namespace Org.BouncyCastle.Math.EC.Tests private void ImplTestMultiply(ECPoint p, int numBits) { BigInteger k = new BigInteger(numBits, secRand); - ECPoint reff = Multiply(p, k); + ECPoint reff = ECAlgorithms.ReferenceMultiply(p, k); ECPoint q = p.Multiply(k); AssertPointsEqual("ECPoint.Multiply is incorrect", reff, q); } @@ -355,7 +326,7 @@ namespace Org.BouncyCastle.Math.EC.Tests do { - ECPoint reff = Multiply(p, k); + ECPoint reff = ECAlgorithms.ReferenceMultiply(p, k); ECPoint q = p.Multiply(k); AssertPointsEqual("ECPoint.Multiply is incorrect", reff, q); k = k.Add(BigInteger.One); |