summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/asn1/pkcs/PrivateKeyInfo.cs4
-rw-r--r--crypto/src/asn1/sec/ECPrivateKeyStructure.cs58
-rw-r--r--crypto/src/openssl/PEMReader.cs2
-rw-r--r--crypto/src/pkcs/PrivateKeyInfoFactory.cs33
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs15
-rw-r--r--crypto/test/src/asn1/test/X9Test.cs22
6 files changed, 96 insertions, 38 deletions
diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
index 404277ba6..c5be7a315 100644
--- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
+++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs
@@ -29,14 +29,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj));
         }
 
-        public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Object privateKey)
+        public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Encodable privateKey)
             : this(algID, privateKey, null)
         {
         }
 
         public PrivateKeyInfo(
             AlgorithmIdentifier	algID,
-            Asn1Object			privateKey,
+            Asn1Encodable       privateKey,
             Asn1Set				attributes)
         {
             this.algID = algID;
diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs
index 8d805fa30..32e020c0b 100644
--- a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs
+++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs
@@ -23,6 +23,7 @@ namespace Org.BouncyCastle.Asn1.Sec
             return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj));
         }
 
+        [Obsolete("Use 'GetInstance' instead")]
         public ECPrivateKeyStructure(
             Asn1Sequence seq)
         {
@@ -32,6 +33,7 @@ namespace Org.BouncyCastle.Asn1.Sec
             this.seq = seq;
         }
 
+        [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")]
         public ECPrivateKeyStructure(
             BigInteger key)
         {
@@ -44,12 +46,30 @@ namespace Org.BouncyCastle.Asn1.Sec
         }
 
         public ECPrivateKeyStructure(
+            int         orderBitLength,
+            BigInteger  key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+            if (orderBitLength < key.BitLength)
+                throw new ArgumentException("must be >= key bitlength", "orderBitLength");
+
+            byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key);
+
+            this.seq = new DerSequence(
+                new DerInteger(1),
+                new DerOctetString(bytes));
+        }
+
+        [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")]
+        public ECPrivateKeyStructure(
             BigInteger		key,
             Asn1Encodable	parameters)
             : this(key, null, parameters)
         {
         }
 
+        [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")]
         public ECPrivateKeyStructure(
             BigInteger		key,
             DerBitString	publicKey,
@@ -75,6 +95,44 @@ namespace Org.BouncyCastle.Asn1.Sec
             this.seq = new DerSequence(v);
         }
 
+        public ECPrivateKeyStructure(
+            int             orderBitLength,
+            BigInteger      key,
+            Asn1Encodable   parameters)
+            : this(orderBitLength, key, null, parameters)
+        {
+        }
+
+        public ECPrivateKeyStructure(
+            int             orderBitLength,
+            BigInteger      key,
+            DerBitString    publicKey,
+            Asn1Encodable   parameters)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+            if (orderBitLength < key.BitLength)
+                throw new ArgumentException("must be >= key bitlength", "orderBitLength");
+
+            byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key);
+
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                new DerInteger(1),
+                new DerOctetString(bytes));
+
+            if (parameters != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, parameters));
+            }
+
+            if (publicKey != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, publicKey));
+            }
+
+            this.seq = new DerSequence(v);
+        }
+
         public virtual BigInteger GetKey()
         {
             Asn1OctetString octs = (Asn1OctetString) seq[1];
diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs
index 987f4471c..9a5f99b1a 100644
--- a/crypto/src/openssl/PEMReader.cs
+++ b/crypto/src/openssl/PEMReader.cs
@@ -311,7 +311,7 @@ namespace Org.BouncyCastle.OpenSsl
 
                     case "EC":
                     {
-                        ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq);
+                        ECPrivateKeyStructure pKey = ECPrivateKeyStructure.GetInstance(seq);
                         AlgorithmIdentifier algId = new AlgorithmIdentifier(
                             X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters());
 
diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
index c6aab4884..aafc4c292 100644
--- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
@@ -106,49 +106,46 @@ namespace Org.BouncyCastle.Pkcs
 
             if (key is ECPrivateKeyParameters)
             {
-                ECPrivateKeyParameters _key = (ECPrivateKeyParameters)key;
+                ECPrivateKeyParameters priv = (ECPrivateKeyParameters)key;
+                ECDomainParameters dp = priv.Parameters;
+                int orderBitLength = dp.N.BitLength;
+
                 AlgorithmIdentifier algID;
                 ECPrivateKeyStructure ec;
 
-                if (_key.AlgorithmName == "ECGOST3410")
+                if (priv.AlgorithmName == "ECGOST3410")
                 {
-                    if (_key.PublicKeyParamSet == null)
+                    if (priv.PublicKeyParamSet == null)
                         throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
 
                     Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
-                        _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+                        priv.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
 
-                    algID = new AlgorithmIdentifier(
-                        CryptoProObjectIdentifiers.GostR3410x2001,
-                        gostParams.ToAsn1Object());
+                    algID = new AlgorithmIdentifier(CryptoProObjectIdentifiers.GostR3410x2001, gostParams);
 
                     // TODO Do we need to pass any parameters here?
-                    ec = new ECPrivateKeyStructure(_key.D);
+                    ec = new ECPrivateKeyStructure(orderBitLength, priv.D);
                 }
                 else
                 {
                     X962Parameters x962;
-                    if (_key.PublicKeyParamSet == null)
+                    if (priv.PublicKeyParamSet == null)
                     {
-                        ECDomainParameters kp = _key.Parameters;
-                        X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed());
-
+                        X9ECParameters ecP = new X9ECParameters(dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed());
                         x962 = new X962Parameters(ecP);
                     }
                     else
                     {
-                        x962 = new X962Parameters(_key.PublicKeyParamSet);
+                        x962 = new X962Parameters(priv.PublicKeyParamSet);
                     }
 
-                    Asn1Object x962Object = x962.ToAsn1Object();
-
                     // TODO Possible to pass the publicKey bitstring here?
-                    ec = new ECPrivateKeyStructure(_key.D, x962Object);
+                    ec = new ECPrivateKeyStructure(orderBitLength, priv.D, x962);
 
-                    algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962Object);
+                    algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962);
                 }
 
-                return new PrivateKeyInfo(algID, ec.ToAsn1Object());
+                return new PrivateKeyInfo(algID, ec);
             }
 
             if (key is Gost3410PrivateKeyParameters)
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index b9538b33d..8c2ecfdb0 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -117,8 +117,7 @@ namespace Org.BouncyCastle.Security
                     x9 = new X9ECParameters((Asn1Sequence)para.Parameters);
                 }
 
-                ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
-                    Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey()));
+                ECPrivateKeyStructure ec = ECPrivateKeyStructure.GetInstance(keyInfo.ParsePrivateKey());
                 BigInteger d = ec.GetKey();
 
                 if (para.IsNamedCurve)
@@ -134,24 +133,24 @@ namespace Org.BouncyCastle.Security
                 Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
                     Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
 
+                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+                if (ecP == null)
+                    throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
+
                 Asn1Object privKey = keyInfo.ParsePrivateKey();
                 ECPrivateKeyStructure ec;
 
                 if (privKey is DerInteger)
                 {
                     // TODO Do we need to pass any parameters here?
-                    ec = new ECPrivateKeyStructure(((DerInteger)privKey).Value);
+                    ec = new ECPrivateKeyStructure(ecP.N.BitLength, ((DerInteger)privKey).Value);
                 }
                 else
                 {
                     ec = ECPrivateKeyStructure.GetInstance(privKey);
                 }
 
-                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
-
-                if (ecP == null)
-                    throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
-
                 return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet);
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
diff --git a/crypto/test/src/asn1/test/X9Test.cs b/crypto/test/src/asn1/test/X9Test.cs
index e310811ea..db2541f7c 100644
--- a/crypto/test/src/asn1/test/X9Test.cs
+++ b/crypto/test/src/asn1/test/X9Test.cs
@@ -27,13 +27,13 @@ namespace Org.BouncyCastle.Asn1.Tests
             + "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED"
             + "IAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
 
-        private static readonly byte[] namedPriv = Base64.Decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK");
+        private static readonly byte[] namedPriv = Base64.Decode("MDkCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEHzAdAgEBBBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo=");
         private static readonly byte[] expPriv = Base64.Decode(
-              "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4"
-            + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU"
-            + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks"
-            + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC"
-            + "AQEECDAGAgEBBAEU");
+              "MIIBBAIBADCB1wYHKoZIzj0CATCBywIBATApBgcqhkjOPQEBAh5///////////////9///////"
+            + "+AAAAAAAB///////8wVwQef///////////////f///////gAAAAAAAf//////8BB4lVwX6KjBmVL"
+            + "H0ywPWp1CjDCUBAtSYhxfZuhWrbT4DFQB9c3QWj/40cbYKhXaGoZR107+i/wQfA2doro4Yu5LPzw"
+            + "BclJqixtlIU9DmYLv4VLHJUF/pWgIef///////////////f///l13rQbOmBXw8QyFGUmVRAgEBBC"
+            + "UwIwIBAQQeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU");
 
         private void EncodePublicKey()
         {
@@ -99,14 +99,15 @@ namespace Org.BouncyCastle.Asn1.Tests
 
         private void EncodePrivateKey()
         {
-            X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3);
+            X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime192v1);
 
             //
             // named curve
             //
             X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1);
 
-            PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.Ten).ToAsn1Object());
+            PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params),
+                new ECPrivateKeyStructure(ecP.N.BitLength, BigInteger.Ten).ToAsn1Object());
 
             if (!Arrays.AreEqual(info.GetEncoded(), namedPriv))
             {
@@ -123,9 +124,12 @@ namespace Org.BouncyCastle.Asn1.Tests
             //
             // explicit curve parameters
             //
+            ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3);
+
             _params = new X962Parameters(ecP);
 
-            info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.ValueOf(20)).ToAsn1Object());
+            info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params),
+                new ECPrivateKeyStructure(ecP.N.BitLength, BigInteger.ValueOf(20)).ToAsn1Object());
 
             if (!Arrays.AreEqual(info.GetEncoded(), expPriv))
             {