diff --git a/crypto/src/asn1/x9/X9Curve.cs b/crypto/src/asn1/x9/X9Curve.cs
index b92e7b3b5..f05a946c2 100644
--- a/crypto/src/asn1/x9/X9Curve.cs
+++ b/crypto/src/asn1/x9/X9Curve.cs
@@ -15,51 +15,50 @@ namespace Org.BouncyCastle.Asn1.X9
{
private readonly ECCurve curve;
private readonly byte[] seed;
- private readonly DerObjectIdentifier fieldIdentifier;
+ private readonly DerObjectIdentifier fieldIdentifier;
- public X9Curve(
+ public X9Curve(
ECCurve curve)
- : this(curve, null)
+ : this(curve, null)
{
- this.curve = curve;
}
- public X9Curve(
+ public X9Curve(
ECCurve curve,
byte[] seed)
{
- if (curve == null)
- throw new ArgumentNullException("curve");
+ if (curve == null)
+ throw new ArgumentNullException("curve");
- this.curve = curve;
+ this.curve = curve;
this.seed = Arrays.Clone(seed);
- if (curve is FpCurve)
- {
- this.fieldIdentifier = X9ObjectIdentifiers.PrimeField;
- }
- else if (curve is F2mCurve)
- {
- this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField;
- }
- else
- {
- throw new ArgumentException("This type of ECCurve is not implemented");
- }
- }
-
- public X9Curve(
+ if (ECAlgorithms.IsFpCurve(curve))
+ {
+ this.fieldIdentifier = X9ObjectIdentifiers.PrimeField;
+ }
+ else if (ECAlgorithms.IsF2mCurve(curve))
+ {
+ this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField;
+ }
+ else
+ {
+ throw new ArgumentException("This type of ECCurve is not implemented");
+ }
+ }
+
+ public X9Curve(
X9FieldID fieldID,
Asn1Sequence seq)
{
- if (fieldID == null)
- throw new ArgumentNullException("fieldID");
- if (seq == null)
- throw new ArgumentNullException("seq");
+ if (fieldID == null)
+ throw new ArgumentNullException("fieldID");
+ if (seq == null)
+ throw new ArgumentNullException("seq");
- this.fieldIdentifier = fieldID.Identifier;
+ this.fieldIdentifier = fieldID.Identifier;
- if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField))
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField))
{
BigInteger q = ((DerInteger) fieldID.Parameters).Value;
X9FieldElement x9A = new X9FieldElement(q, (Asn1OctetString) seq[0]);
@@ -68,54 +67,54 @@ namespace Org.BouncyCastle.Asn1.X9
}
else
{
- if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
- {
- // Characteristic two field
- DerSequence parameters = (DerSequence)fieldID.Parameters;
- int m = ((DerInteger)parameters[0]).Value.IntValue;
- DerObjectIdentifier representation
- = (DerObjectIdentifier)parameters[1];
-
- int k1 = 0;
- int k2 = 0;
- int k3 = 0;
- if (representation.Equals(X9ObjectIdentifiers.TPBasis))
- {
- // Trinomial basis representation
- k1 = ((DerInteger)parameters[2]).Value.IntValue;
- }
- else
- {
- // Pentanomial basis representation
- DerSequence pentanomial = (DerSequence) parameters[2];
- k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
- k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
- k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
- }
- X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]);
- X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]);
- // TODO Is it possible to get the order (n) and cofactor(h) too?
- curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
- }
- }
-
- if (seq.Count == 3)
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
+ {
+ // Characteristic two field
+ DerSequence parameters = (DerSequence)fieldID.Parameters;
+ int m = ((DerInteger)parameters[0]).Value.IntValue;
+ DerObjectIdentifier representation
+ = (DerObjectIdentifier)parameters[1];
+
+ int k1 = 0;
+ int k2 = 0;
+ int k3 = 0;
+ if (representation.Equals(X9ObjectIdentifiers.TPBasis))
+ {
+ // Trinomial basis representation
+ k1 = ((DerInteger)parameters[2]).Value.IntValue;
+ }
+ else
+ {
+ // Pentanomial basis representation
+ DerSequence pentanomial = (DerSequence) parameters[2];
+ k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
+ k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
+ k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
+ }
+ X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]);
+ X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]);
+ // TODO Is it possible to get the order (n) and cofactor(h) too?
+ curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
+ }
+ }
+
+ if (seq.Count == 3)
{
seed = ((DerBitString) seq[2]).GetBytes();
}
}
- public ECCurve Curve
+ public ECCurve Curve
{
- get { return curve; }
+ get { return curve; }
}
- public byte[] GetSeed()
+ public byte[] GetSeed()
{
return Arrays.Clone(seed);
}
- /**
+ /**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* Curve ::= Sequence {
@@ -127,21 +126,21 @@ namespace Org.BouncyCastle.Asn1.X9
*/
public override Asn1Object ToAsn1Object()
{
- Asn1EncodableVector v = new Asn1EncodableVector();
-
- if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)
- || fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
- {
- v.Add(new X9FieldElement(curve.A).ToAsn1Object());
- v.Add(new X9FieldElement(curve.B).ToAsn1Object());
- }
-
- if (seed != null)
- {
- v.Add(new DerBitString(seed));
- }
-
- return new DerSequence(v);
- }
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)
+ || fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
+ {
+ v.Add(new X9FieldElement(curve.A).ToAsn1Object());
+ v.Add(new X9FieldElement(curve.B).ToAsn1Object());
+ }
+
+ if (seed != null)
+ {
+ v.Add(new DerBitString(seed));
+ }
+
+ return new DerSequence(v);
+ }
}
}
diff --git a/crypto/src/asn1/x9/X9ECParameters.cs b/crypto/src/asn1/x9/X9ECParameters.cs
index d025b36ce..6389defa8 100644
--- a/crypto/src/asn1/x9/X9ECParameters.cs
+++ b/crypto/src/asn1/x9/X9ECParameters.cs
@@ -2,6 +2,7 @@ using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.Field;
namespace Org.BouncyCastle.Asn1.X9
{
@@ -19,7 +20,7 @@ namespace Org.BouncyCastle.Asn1.X9
private BigInteger h;
private byte[] seed;
- public X9ECParameters(
+ public X9ECParameters(
Asn1Sequence seq)
{
if (!(seq[0] is DerInteger)
@@ -28,7 +29,7 @@ namespace Org.BouncyCastle.Asn1.X9
throw new ArgumentException("bad version in X9ECParameters");
}
- X9Curve x9c = null;
+ X9Curve x9c = null;
if (seq[2] is X9Curve)
{
x9c = (X9Curve) seq[2];
@@ -36,14 +37,14 @@ namespace Org.BouncyCastle.Asn1.X9
else
{
x9c = new X9Curve(
- new X9FieldID(
- (Asn1Sequence) seq[1]),
- (Asn1Sequence) seq[2]);
+ new X9FieldID(
+ (Asn1Sequence) seq[1]),
+ (Asn1Sequence) seq[2]);
}
- this.curve = x9c.Curve;
+ this.curve = x9c.Curve;
- if (seq[3] is X9ECPoint)
+ if (seq[3] is X9ECPoint)
{
this.g = ((X9ECPoint) seq[3]).Point;
}
@@ -52,16 +53,16 @@ namespace Org.BouncyCastle.Asn1.X9
this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
}
- this.n = ((DerInteger) seq[4]).Value;
+ this.n = ((DerInteger) seq[4]).Value;
this.seed = x9c.GetSeed();
- if (seq.Count == 6)
+ if (seq.Count == 6)
{
this.h = ((DerInteger) seq[5]).Value;
}
}
- public X9ECParameters(
+ public X9ECParameters(
ECCurve curve,
ECPoint g,
BigInteger n)
@@ -69,7 +70,7 @@ namespace Org.BouncyCastle.Asn1.X9
{
}
- public X9ECParameters(
+ public X9ECParameters(
ECCurve curve,
ECPoint g,
BigInteger n,
@@ -78,7 +79,7 @@ namespace Org.BouncyCastle.Asn1.X9
{
}
- public X9ECParameters(
+ public X9ECParameters(
ECCurve curve,
ECPoint g,
BigInteger n,
@@ -91,53 +92,68 @@ namespace Org.BouncyCastle.Asn1.X9
this.h = h;
this.seed = seed;
- if (curve is FpCurve)
- {
- this.fieldID = new X9FieldID(((FpCurve) curve).Q);
- }
- else if (curve is F2mCurve)
- {
- F2mCurve curveF2m = (F2mCurve) curve;
- this.fieldID = new X9FieldID(curveF2m.M, curveF2m.K1,
- curveF2m.K2, curveF2m.K3);
- }
+ if (ECAlgorithms.IsFpCurve(curve))
+ {
+ this.fieldID = new X9FieldID(curve.Field.Characteristic);
+ }
+ else if (ECAlgorithms.IsF2mCurve(curve))
+ {
+ IPolynomialExtensionField field = (IPolynomialExtensionField)curve.Field;
+ int[] exponents = field.MinimalPolynomial.GetExponentsPresent();
+ if (exponents.Length == 3)
+ {
+ this.fieldID = new X9FieldID(exponents[2], exponents[1]);
+ }
+ else if (exponents.Length == 5)
+ {
+ this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]);
+ }
+ else
+ {
+ throw new ArgumentException("Only trinomial and pentomial curves are supported");
+ }
+ }
+ else
+ {
+ throw new ArgumentException("'curve' is of an unsupported type");
+ }
}
- public ECCurve Curve
+ public ECCurve Curve
{
- get { return curve; }
+ get { return curve; }
}
- public ECPoint G
+ public ECPoint G
{
get { return g; }
}
- public BigInteger N
+ public BigInteger N
{
get { return n; }
}
- public BigInteger H
+ public BigInteger H
{
get
- {
- if (h == null)
- {
- // TODO - this should be calculated, it will cause issues with custom curves.
- return BigInteger.One;
- }
-
- return h;
- }
+ {
+ if (h == null)
+ {
+ // TODO - this should be calculated, it will cause issues with custom curves.
+ return BigInteger.One;
+ }
+
+ return h;
+ }
}
- public byte[] GetSeed()
+ public byte[] GetSeed()
{
return seed;
}
- /**
+ /**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* ECParameters ::= Sequence {
@@ -153,18 +169,18 @@ namespace Org.BouncyCastle.Asn1.X9
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(
- new DerInteger(1),
- fieldID,
- new X9Curve(curve, seed),
- new X9ECPoint(g),
- new DerInteger(n));
+ new DerInteger(1),
+ fieldID,
+ new X9Curve(curve, seed),
+ new X9ECPoint(g),
+ new DerInteger(n));
- if (h != null)
+ if (h != null)
{
v.Add(new DerInteger(h));
}
- return new DerSequence(v);
+ return new DerSequence(v);
}
}
}
diff --git a/crypto/src/asn1/x9/X9FieldID.cs b/crypto/src/asn1/x9/X9FieldID.cs
index c51cc4df2..58823a285 100644
--- a/crypto/src/asn1/x9/X9FieldID.cs
+++ b/crypto/src/asn1/x9/X9FieldID.cs
@@ -1,3 +1,5 @@
+using System;
+
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Asn1.X9
@@ -12,80 +14,100 @@ namespace Org.BouncyCastle.Asn1.X9
private readonly DerObjectIdentifier id;
private readonly Asn1Object parameters;
- /**
- * Constructor for elliptic curves over prime fields
- * <code>F<sub>2</sub></code>.
- * @param primeP The prime <code>p</code> defining the prime field.
- */
- public X9FieldID(
- BigInteger primeP)
- {
- this.id = X9ObjectIdentifiers.PrimeField;
- this.parameters = new DerInteger(primeP);
- }
+ /**
+ * Constructor for elliptic curves over prime fields
+ * <code>F<sub>2</sub></code>.
+ * @param primeP The prime <code>p</code> defining the prime field.
+ */
+ public X9FieldID(
+ BigInteger primeP)
+ {
+ this.id = X9ObjectIdentifiers.PrimeField;
+ this.parameters = new DerInteger(primeP);
+ }
- /**
- * Constructor for elliptic curves over binary fields
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>..
- */
- public X9FieldID(
- int m,
- int k1,
- int k2,
- int k3)
- {
- this.id = X9ObjectIdentifiers.CharacteristicTwoField;
+ /**
+ * Constructor for elliptic curves over binary fields
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ */
+ public X9FieldID(int m, int k1)
+ : this(m, k1, 0, 0)
+ {
+ }
- Asn1EncodableVector fieldIdParams = new Asn1EncodableVector(new DerInteger(m));
+ /**
+ * Constructor for elliptic curves over binary fields
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>..
+ */
+ public X9FieldID(
+ int m,
+ int k1,
+ int k2,
+ int k3)
+ {
+ this.id = X9ObjectIdentifiers.CharacteristicTwoField;
+
+ Asn1EncodableVector fieldIdParams = new Asn1EncodableVector(new DerInteger(m));
- if (k2 == 0)
- {
- fieldIdParams.Add(
- X9ObjectIdentifiers.TPBasis,
- new DerInteger(k1));
- }
- else
- {
- fieldIdParams.Add(
- X9ObjectIdentifiers.PPBasis,
- new DerSequence(
- new DerInteger(k1),
- new DerInteger(k2),
- new DerInteger(k3)));
- }
+ if (k2 == 0)
+ {
+ if (k3 != 0)
+ throw new ArgumentException("inconsistent k values");
- this.parameters = new DerSequence(fieldIdParams);
- }
+ fieldIdParams.Add(
+ X9ObjectIdentifiers.TPBasis,
+ new DerInteger(k1));
+ }
+ else
+ {
+ if (k2 <= k1 || k3 <= k2)
+ throw new ArgumentException("inconsistent k values");
- internal X9FieldID(
- Asn1Sequence seq)
- {
- this.id = (DerObjectIdentifier) seq[0];
- this.parameters = (Asn1Object) seq[1];
- }
+ fieldIdParams.Add(
+ X9ObjectIdentifiers.PPBasis,
+ new DerSequence(
+ new DerInteger(k1),
+ new DerInteger(k2),
+ new DerInteger(k3)));
+ }
+
+ this.parameters = new DerSequence(fieldIdParams);
+ }
+
+ internal X9FieldID(
+ Asn1Sequence seq)
+ {
+ this.id = (DerObjectIdentifier) seq[0];
+ this.parameters = (Asn1Object) seq[1];
+ }
- public DerObjectIdentifier Identifier
+ public DerObjectIdentifier Identifier
{
get { return id; }
}
- public Asn1Object Parameters
+ public Asn1Object Parameters
{
get { return parameters; }
}
- /**
+ /**
* Produce a Der encoding of the following structure.
* <pre>
* FieldID ::= Sequence {
@@ -96,7 +118,7 @@ namespace Org.BouncyCastle.Asn1.X9
*/
public override Asn1Object ToAsn1Object()
{
- return new DerSequence(id, parameters);
+ return new DerSequence(id, parameters);
}
}
}
diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs
index be4fd1b14..06288132b 100644
--- a/crypto/src/math/ec/ECAlgorithms.cs
+++ b/crypto/src/math/ec/ECAlgorithms.cs
@@ -1,93 +1,105 @@
using System;
-using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.Field;
namespace Org.BouncyCastle.Math.EC
{
- public class ECAlgorithms
- {
- public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a,
- ECPoint Q, BigInteger b)
- {
- ECCurve c = P.Curve;
- if (!c.Equals(Q.Curve))
- throw new ArgumentException("P and Q must be on same curve");
+ public class ECAlgorithms
+ {
+ public static bool IsF2mCurve(ECCurve c)
+ {
+ IFiniteField field = c.Field;
+ return field.Dimension > 1 && field.Characteristic.Equals(BigInteger.Two)
+ && field is IPolynomialExtensionField;
+ }
- // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
- if (c is F2mCurve)
- {
- F2mCurve f2mCurve = (F2mCurve) c;
- if (f2mCurve.IsKoblitz)
- {
- return P.Multiply(a).Add(Q.Multiply(b));
- }
- }
+ public static bool IsFpCurve(ECCurve c)
+ {
+ return c.Field.Dimension == 1;
+ }
- return ImplShamirsTrick(P, a, Q, b);
- }
+ public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a,
+ ECPoint Q, BigInteger b)
+ {
+ ECCurve c = P.Curve;
+ if (!c.Equals(Q.Curve))
+ throw new ArgumentException("P and Q must be on same curve");
- /*
- * "Shamir's Trick", originally due to E. G. Straus
- * (Addition chains of vectors. American Mathematical Monthly,
- * 71(7):806-808, Aug./Sept. 1964)
- *
- * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
- * and scalar l = (lm?, ... , l1, l0).
- * Output: R = k * P + l * Q.
- * 1: Z <- P + Q
- * 2: R <- O
- * 3: for i from m-1 down to 0 do
- * 4: R <- R + R {point doubling}
- * 5: if (ki = 1) and (li = 0) then R <- R + P end if
- * 6: if (ki = 0) and (li = 1) then R <- R + Q end if
- * 7: if (ki = 1) and (li = 1) then R <- R + Z end if
- * 8: end for
- * 9: return R
- */
- public static ECPoint ShamirsTrick(
- ECPoint P,
- BigInteger k,
- ECPoint Q,
- BigInteger l)
- {
- if (!P.Curve.Equals(Q.Curve))
- throw new ArgumentException("P and Q must be on same curve");
+ // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
+ if (c is F2mCurve)
+ {
+ F2mCurve f2mCurve = (F2mCurve) c;
+ if (f2mCurve.IsKoblitz)
+ {
+ return P.Multiply(a).Add(Q.Multiply(b));
+ }
+ }
- return ImplShamirsTrick(P, k, Q, l);
- }
+ return ImplShamirsTrick(P, a, Q, b);
+ }
- private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k,
- ECPoint Q, BigInteger l)
- {
- int m = System.Math.Max(k.BitLength, l.BitLength);
- ECPoint Z = P.Add(Q);
- ECPoint R = P.Curve.Infinity;
+ /*
+ * "Shamir's Trick", originally due to E. G. Straus
+ * (Addition chains of vectors. American Mathematical Monthly,
+ * 71(7):806-808, Aug./Sept. 1964)
+ *
+ * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
+ * and scalar l = (lm?, ... , l1, l0).
+ * Output: R = k * P + l * Q.
+ * 1: Z <- P + Q
+ * 2: R <- O
+ * 3: for i from m-1 down to 0 do
+ * 4: R <- R + R {point doubling}
+ * 5: if (ki = 1) and (li = 0) then R <- R + P end if
+ * 6: if (ki = 0) and (li = 1) then R <- R + Q end if
+ * 7: if (ki = 1) and (li = 1) then R <- R + Z end if
+ * 8: end for
+ * 9: return R
+ */
+ public static ECPoint ShamirsTrick(
+ ECPoint P,
+ BigInteger k,
+ ECPoint Q,
+ BigInteger l)
+ {
+ if (!P.Curve.Equals(Q.Curve))
+ throw new ArgumentException("P and Q must be on same curve");
- for (int i = m - 1; i >= 0; --i)
- {
- R = R.Twice();
+ return ImplShamirsTrick(P, k, Q, l);
+ }
- if (k.TestBit(i))
- {
- if (l.TestBit(i))
- {
- R = R.Add(Z);
- }
- else
- {
- R = R.Add(P);
- }
- }
- else
- {
- if (l.TestBit(i))
- {
- R = R.Add(Q);
- }
- }
- }
+ private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k,
+ ECPoint Q, BigInteger l)
+ {
+ int m = System.Math.Max(k.BitLength, l.BitLength);
+ ECPoint Z = P.Add(Q);
+ ECPoint R = P.Curve.Infinity;
- return R;
- }
- }
+ for (int i = m - 1; i >= 0; --i)
+ {
+ R = R.Twice();
+
+ if (k.TestBit(i))
+ {
+ if (l.TestBit(i))
+ {
+ R = R.Add(Z);
+ }
+ else
+ {
+ R = R.Add(P);
+ }
+ }
+ else
+ {
+ if (l.TestBit(i))
+ {
+ R = R.Add(Q);
+ }
+ }
+ }
+
+ return R;
+ }
+ }
}
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index ab98af8f1..6f4492e5c 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -2,52 +2,63 @@ using System;
using System.Collections;
using Org.BouncyCastle.Math.EC.Abc;
+using Org.BouncyCastle.Math.Field;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC
{
/// <remarks>Base class for an elliptic curve.</remarks>
public abstract class ECCurve
{
- internal ECFieldElement a, b;
+ protected IFiniteField m_field;
+ protected ECFieldElement m_a, m_b;
+
+ protected ECCurve(IFiniteField field)
+ {
+ this.m_field = field;
+ }
public abstract int FieldSize { get; }
public abstract ECFieldElement FromBigInteger(BigInteger x);
public abstract ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression);
public abstract ECPoint Infinity { get; }
- public ECFieldElement A
+ public virtual IFiniteField Field
{
- get { return a; }
+ get { return m_field; }
}
- public ECFieldElement B
+ public virtual ECFieldElement A
{
- get { return b; }
+ get { return m_a; }
}
- public override bool Equals(
- object obj)
+ public virtual ECFieldElement B
{
- if (obj == this)
- return true;
-
- ECCurve other = obj as ECCurve;
+ get { return m_b; }
+ }
- if (other == null)
+ public virtual bool Equals(ECCurve other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
return false;
-
- return Equals(other);
+ return Field.Equals(other.Field)
+ && A.Equals(other.A)
+ && B.Equals(other.B);
}
- protected bool Equals(
- ECCurve other)
+ public override bool Equals(object obj)
{
- return a.Equals(other.a) && b.Equals(other.b);
+ return Equals(obj as ECCurve);
}
public override int GetHashCode()
{
- return a.GetHashCode() ^ b.GetHashCode();
+ return Field.GetHashCode()
+ ^ Integers.RotateLeft(A.GetHashCode(), 8)
+ ^ Integers.RotateLeft(B.GetHashCode(), 16);
}
protected abstract ECPoint DecompressPoint(int yTilde, BigInteger X1);
@@ -112,17 +123,19 @@ namespace Org.BouncyCastle.Math.EC
/**
* Elliptic curve over Fp
*/
- public class FpCurve : ECCurve
+ public class FpCurve
+ : ECCurve
{
private readonly BigInteger q, r;
private readonly FpPoint infinity;
public FpCurve(BigInteger q, BigInteger a, BigInteger b)
+ : base(FiniteFields.GetPrimeField(q))
{
this.q = q;
this.r = FpFieldElement.CalculateResidue(q);
- this.a = FromBigInteger(a);
- this.b = FromBigInteger(b);
+ this.m_a = FromBigInteger(a);
+ this.m_b = FromBigInteger(b);
this.infinity = new FpPoint(this, null, null);
}
@@ -164,7 +177,7 @@ namespace Org.BouncyCastle.Math.EC
BigInteger X1)
{
ECFieldElement x = FromBigInteger(X1);
- ECFieldElement alpha = x.Multiply(x.Square().Add(a)).Add(b);
+ ECFieldElement alpha = x.Multiply(x.Square().Add(m_a)).Add(m_b);
ECFieldElement beta = alpha.Sqrt();
//
@@ -185,39 +198,44 @@ namespace Org.BouncyCastle.Math.EC
return new FpPoint(this, x, beta, true);
}
+ }
- public override bool Equals(
- object obj)
+ /**
+ * 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
+ {
+ private static IFiniteField BuildField(int m, int k1, int k2, int k3)
{
- if (obj == this)
- return true;
+ if (k1 == 0)
+ {
+ throw new ArgumentException("k1 must be > 0");
+ }
- FpCurve other = obj as FpCurve;
+ if (k2 == 0)
+ {
+ if (k3 != 0)
+ {
+ throw new ArgumentException("k3 must be 0 if k2 == 0");
+ }
- if (other == null)
- return false;
+ return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, m });
+ }
- return Equals(other);
- }
+ if (k2 <= k1)
+ {
+ throw new ArgumentException("k2 must be > k1");
+ }
- protected bool Equals(
- FpCurve other)
- {
- return base.Equals(other) && q.Equals(other.q);
- }
+ if (k3 <= k2)
+ {
+ throw new ArgumentException("k3 must be > k2");
+ }
- public override int GetHashCode()
- {
- return base.GetHashCode() ^ q.GetHashCode();
+ return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
}
- }
- /**
- * 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
- {
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
*/
@@ -391,6 +409,7 @@ namespace Org.BouncyCastle.Math.EC
BigInteger b,
BigInteger n,
BigInteger h)
+ : base(BuildField(m, k1, k2, k3))
{
this.m = m;
this.k1 = k1;
@@ -417,8 +436,8 @@ namespace Org.BouncyCastle.Math.EC
throw new ArgumentException("k3 must be > k2");
}
- this.a = FromBigInteger(a);
- this.b = FromBigInteger(b);
+ this.m_a = FromBigInteger(a);
+ this.m_b = FromBigInteger(b);
}
public override ECPoint Infinity
@@ -444,10 +463,7 @@ namespace Org.BouncyCastle.Math.EC
{
get
{
- return n != null && h != null
- && (a.ToBigInteger().Equals(BigInteger.Zero)
- || a.ToBigInteger().Equals(BigInteger.One))
- && b.ToBigInteger().Equals(BigInteger.One);
+ return n != null && h != null && m_a.BitLength <= 1 && m_b.IsOne;
}
}
@@ -514,7 +530,7 @@ namespace Org.BouncyCastle.Math.EC
ECFieldElement yp = null;
if (xp.ToBigInteger().SignValue == 0)
{
- yp = (F2mFieldElement)b;
+ yp = (F2mFieldElement)m_b;
for (int i = 0; i < m - 1; i++)
{
yp = yp.Square();
@@ -522,7 +538,7 @@ namespace Org.BouncyCastle.Math.EC
}
else
{
- ECFieldElement beta = xp.Add(a).Add(b.Multiply(xp.Square().Invert()));
+ ECFieldElement beta = xp.Add(m_a).Add(m_b.Multiply(xp.Square().Invert()));
ECFieldElement z = solveQuadradicEquation(beta);
if (z == null)
@@ -580,35 +596,6 @@ namespace Org.BouncyCastle.Math.EC
return z;
}
- public override bool Equals(
- object obj)
- {
- if (obj == this)
- return true;
-
- F2mCurve other = obj as F2mCurve;
-
- if (other == null)
- return false;
-
- return Equals(other);
- }
-
- protected bool Equals(
- F2mCurve other)
- {
- return m == other.m
- && k1 == other.k1
- && k2 == other.k2
- && k3 == other.k3
- && base.Equals(other);
- }
-
- public override int GetHashCode()
- {
- return base.GetHashCode() ^ m ^ k1 ^ k2 ^ k3;
- }
-
public int M
{
get { return m; }
|