From 73cb18129e632b44ddae7f9c589fd9c17c77d3ca Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 22 Jan 2014 11:40:05 +0700 Subject: Use new Math.Field classes in EC curves, and avoid casting in client code --- crypto/src/asn1/x9/X9Curve.cs | 161 +++++++++++++++++------------------ crypto/src/asn1/x9/X9ECParameters.cs | 106 +++++++++++++---------- crypto/src/asn1/x9/X9FieldID.cs | 144 ++++++++++++++++++------------- 3 files changed, 224 insertions(+), 187 deletions(-) (limited to 'crypto/src/asn1/x9') 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. *
          *  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.
          * 
          *  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
-		 * F2.
-		 * @param primeP The prime p defining the prime field.
-		 */
-		public X9FieldID(
-			BigInteger primeP)
-		{
-			this.id = X9ObjectIdentifiers.PrimeField;
-			this.parameters = new DerInteger(primeP);
-		}
+        /**
+         * Constructor for elliptic curves over prime fields
+         * F2.
+         * @param primeP The prime p defining the prime field.
+         */
+        public X9FieldID(
+            BigInteger primeP)
+        {
+            this.id = X9ObjectIdentifiers.PrimeField;
+            this.parameters = new DerInteger(primeP);
+        }
 
-		/**
-		 * Constructor for elliptic curves over binary fields
-		 * F2m.
-		 * @param m  The exponent m of
-		 * F2m.
-		 * @param k1 The integer k1 where xm +
-		 * xk3 + xk2 + xk1 + 1
-		 * represents the reduction polynomial f(z).
-		 * @param k2 The integer k2 where xm +
-		 * xk3 + xk2 + xk1 + 1
-		 * represents the reduction polynomial f(z).
-		 * @param k3 The integer k3 where xm +
-		 * xk3 + xk2 + xk1 + 1
-		 * represents the reduction polynomial f(z)..
-		 */
-		public X9FieldID(
-			int m,
-			int k1,
-			int k2,
-			int k3)
-		{
-			this.id = X9ObjectIdentifiers.CharacteristicTwoField;
+        /**
+         * Constructor for elliptic curves over binary fields
+         * F2m.
+         * @param m  The exponent m of
+         * F2m.
+         * @param k1 The integer k1 where xm +
+         * xk1 + 1
+         * represents the reduction polynomial f(z).
+         */
+        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
+         * F2m.
+         * @param m  The exponent m of
+         * F2m.
+         * @param k1 The integer k1 where xm +
+         * xk3 + xk2 + xk1 + 1
+         * represents the reduction polynomial f(z).
+         * @param k2 The integer k2 where xm +
+         * xk3 + xk2 + xk1 + 1
+         * represents the reduction polynomial f(z).
+         * @param k3 The integer k3 where xm +
+         * xk3 + xk2 + xk1 + 1
+         * represents the reduction polynomial f(z)..
+         */
+        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.
          * 
          *  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);
         }
     }
 }
-- 
cgit 1.4.1