summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2019-08-04 14:59:54 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2019-08-04 14:59:54 +0700
commitbbfa024697bd0ec381fc1a0507bd0dedc6696f63 (patch)
treeb8a60695d573c661642f7e3d6636331408ce2f18
parentImprove caching behaviour for algorithms using endomorphisms (diff)
downloadBouncyCastle.NET-ed25519-bbfa024697bd0ec381fc1a0507bd0dedc6696f63.tar.xz
Refactoring in PublicKeyFactory
- add SubjectPublicKeyInfo.ParsePublicKey and use where applicable
- validate GOST3410 public key lengths
-rw-r--r--crypto/src/asn1/x509/SubjectPublicKeyInfo.cs13
-rw-r--r--crypto/src/security/PublicKeyFactory.cs113
-rw-r--r--crypto/test/src/crypto/test/OAEPTest.cs2
3 files changed, 73 insertions, 55 deletions
diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
index 477329b7e..ae44a451f 100644
--- a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
+++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -66,6 +66,18 @@ namespace Org.BouncyCastle.Asn1.X509
 			get { return algID; }
         }
 
+        /**
+         * for when the public key is an encoded object - if the bitstring
+         * can't be decoded this routine raises an IOException.
+         *
+         * @exception IOException - if the bit string doesn't represent a Der
+         * encoded object.
+         */
+        public Asn1Object ParsePublicKey()
+        {
+            return Asn1Object.FromByteArray(keyData.GetOctets());
+        }
+
 		/**
          * for when the public key is an encoded object - if the bitstring
          * can't be decoded this routine raises an IOException.
@@ -73,6 +85,7 @@ namespace Org.BouncyCastle.Asn1.X509
          * @exception IOException - if the bit string doesn't represent a Der
          * encoded object.
          */
+        [Obsolete("Use 'ParsePublicKey' instead")]
         public Asn1Object GetPublicKey()
         {
 			return Asn1Object.FromByteArray(keyData.GetOctets());
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 7a34d71df..7b19f1c0f 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -17,6 +17,7 @@ using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Security
@@ -56,7 +57,7 @@ namespace Org.BouncyCastle.Security
                 || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
             {
                 RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance(
-                    keyInfo.GetPublicKey());
+                    keyInfo.ParsePublicKey());
 
                 return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent);
             }
@@ -64,7 +65,7 @@ namespace Org.BouncyCastle.Security
             {
                 Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
 
-                DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey());
+                DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.ParsePublicKey());
 
                 BigInteger y = dhPublicKey.Y.Value;
 
@@ -101,7 +102,7 @@ namespace Org.BouncyCastle.Security
             {
                 Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
 
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
 
                 return ReadPkcsDHParam(algOid, derY.Value, seq);
             }
@@ -109,7 +110,7 @@ namespace Org.BouncyCastle.Security
             {
                 ElGamalParameter para = new ElGamalParameter(
                     Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
 
                 return new ElGamalPublicKeyParameters(
                     derY.Value,
@@ -118,7 +119,7 @@ namespace Org.BouncyCastle.Security
             else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)
                 || algOid.Equals(OiwObjectIdentifiers.DsaWithSha1))
             {
-                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                DerInteger derY = (DerInteger)keyInfo.ParsePublicKey();
                 Asn1Encodable ae = algID.Parameters;
 
                 DsaParameters parameters = null;
@@ -158,64 +159,57 @@ namespace Org.BouncyCastle.Security
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
             {
-                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
-                    (Asn1Sequence) algID.Parameters);
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
+                DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet;
+
+                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(publicKeyParamSet);
+                if (ecP == null)
+                    return null;
 
                 Asn1OctetString key;
                 try
                 {
-                    key = (Asn1OctetString) keyInfo.GetPublicKey();
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
                 }
-                catch (IOException)
+                catch (IOException e)
                 {
-                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                    throw new ArgumentException("error recovering GOST3410_2001 public key", e);
                 }
 
-                byte[] keyEnc = key.GetOctets();
-                byte[] x = new byte[32];
-                byte[] y = new byte[32];
+                int fieldSize = 32;
+                int keySize = 2 * fieldSize;
 
-                for (int i = 0; i != y.Length; i++)
-                {
-                    x[i] = keyEnc[32 - 1 - i];
-                }
+                byte[] keyEnc = key.GetOctets();
+                if (keyEnc.Length != keySize)
+                    throw new ArgumentException("invalid length for GOST3410_2001 public key");
 
-                for (int i = 0; i != x.Length; i++)
+                byte[] x9Encoding = new byte[1 + keySize];
+                x9Encoding[0] = 0x04;
+                for (int i = 1; i <= fieldSize; ++i)
                 {
-                    y[i] = keyEnc[64 - 1 - i];
+                    x9Encoding[i] = keyEnc[fieldSize - i];
+                    x9Encoding[i + fieldSize] = keyEnc[keySize - i];
                 }
 
-                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
-
-                if (ecP == null)
-                    return null;
-
-                ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y));
+                ECPoint q = ecP.Curve.DecodePoint(x9Encoding);
 
-                return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet);
+                return new ECPublicKeyParameters("ECGOST3410", q, publicKeyParamSet);
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
             {
-                Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
-                    (Asn1Sequence) algID.Parameters);
+                Gost3410PublicKeyAlgParameters algParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
 
-                DerOctetString derY;
+                Asn1OctetString key;
                 try
                 {
-                    derY = (DerOctetString) keyInfo.GetPublicKey();
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
                 }
-                catch (IOException)
+                catch (IOException e)
                 {
-                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                    throw new ArgumentException("error recovering GOST3410_94 public key", e);
                 }
 
-                byte[] keyEnc = derY.GetOctets();
-                byte[] keyBytes = new byte[keyEnc.Length];
-
-                for (int i = 0; i != keyEnc.Length; i++)
-                {
-                    keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
-                }
+                byte[] keyBytes = Arrays.Reverse(key.GetOctets()); // was little endian
 
                 BigInteger y = new BigInteger(1, keyBytes);
 
@@ -236,21 +230,40 @@ namespace Org.BouncyCastle.Security
             else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448))
             {
                 return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0);
-            } else if (
-                algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) ||
-                algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
+            }
+            else if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256)
+                ||   algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
             {
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(algID.Parameters);
+                DerObjectIdentifier publicKeyParamSet = gostParams.PublicKeyParamSet;
 
-                byte[] keyEnc = ((DerOctetString)Asn1Object.FromByteArray(keyInfo.PublicKeyData.GetOctets())).str;
+                ECGost3410Parameters ecDomainParameters =new ECGost3410Parameters(
+                    new ECNamedDomainParameters(publicKeyParamSet, ECGost3410NamedCurves.GetByOid(publicKeyParamSet)),
+                    publicKeyParamSet,
+                    gostParams.DigestParamSet,
+                    gostParams.EncryptionParamSet);
+
+                Asn1OctetString key;
+                try
+                {
+                    key = (Asn1OctetString)keyInfo.ParsePublicKey();
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("error recovering GOST3410_2012 public key", e);
+                }
 
                 int fieldSize = 32;
                 if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
                 {
                     fieldSize = 64;
                 }
-
                 int keySize = 2 * fieldSize;
 
+                byte[] keyEnc = key.GetOctets();
+                if (keyEnc.Length != keySize)
+                    throw new ArgumentException("invalid length for GOST3410_2012 public key");
+
                 byte[] x9Encoding = new byte[1 + keySize];
                 x9Encoding[0] = 0x04;
                 for (int i = 1; i <= fieldSize; ++i)
@@ -259,17 +272,9 @@ namespace Org.BouncyCastle.Security
                     x9Encoding[i + fieldSize] = keyEnc[keySize - i];
                 }
 
-                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters);
-
-                ECGost3410Parameters ecDomainParameters =
-                    new ECGost3410Parameters(
-                        new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet)),
-                        gostParams.PublicKeyParamSet,
-                        gostParams.DigestParamSet,
-                        gostParams.EncryptionParamSet);
-              
-                return new ECPublicKeyParameters(ecDomainParameters.Curve.DecodePoint(x9Encoding), ecDomainParameters);
+                ECPoint q = ecDomainParameters.Curve.DecodePoint(x9Encoding);
 
+                return new ECPublicKeyParameters(q, ecDomainParameters);
             }
             else
             {
diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs
index 204784cee..0d4374db1 100644
--- a/crypto/test/src/crypto/test/OAEPTest.cs
+++ b/crypto/test/src/crypto/test/OAEPTest.cs
@@ -310,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Tests
             //
             Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubKeyEnc);
             RsaPublicKeyStructure pubStruct = RsaPublicKeyStructure.GetInstance(
-                SubjectPublicKeyInfo.GetInstance(pubKeyObj).GetPublicKey());
+                SubjectPublicKeyInfo.GetInstance(pubKeyObj).ParsePublicKey());
 
             //
             // extract the private key info.