summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-06 22:44:18 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-06 22:44:18 +0700
commit9dfd5af9b7ed63a33513599ae3e874c85dea15c3 (patch)
treed7342aad04bca424b56229d1d5eba558bbb4afd3
parentCryptoApiRandomGenerator implements IDisposable (diff)
downloadBouncyCastle.NET-ed25519-9dfd5af9b7ed63a33513599ae3e874c85dea15c3.tar.xz
GOST 2012 private key reading
- see https://github.com/bcgit/bc-csharp/issues/365
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs96
-rw-r--r--crypto/test/src/openssl/test/ReaderTest.cs18
2 files changed, 101 insertions, 13 deletions
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index c4fabae2d..e66224a67 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -130,29 +130,99 @@ namespace Org.BouncyCastle.Security
                 ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
                 return new ECPrivateKeyParameters(d, dParams);
             }
-            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001) ||
+                     algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512) ||
+                     algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256))
             {
-                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(
-                    algID.Parameters.ToAsn1Object());
+                Asn1Object p = algID.Parameters.ToAsn1Object();
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(p);
 
-                X9ECParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+                ECGost3410Parameters ecSpec;
+                BigInteger d;
 
-                if (ecP == null)
-                    throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
+                if (p is Asn1Sequence seq && (seq.Count == 2 || seq.Count == 3))
+                {
+                    X9ECParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+                    if (ecP == null)
+                        throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
 
-                Asn1Object privKey = keyInfo.ParsePrivateKey();
-                ECPrivateKeyStructure ec;
+                    ecSpec = new ECGost3410Parameters(
+                        new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ecP),
+                        gostParams.PublicKeyParamSet,
+                        gostParams.DigestParamSet,
+                        gostParams.EncryptionParamSet);
 
-                if (privKey is DerInteger)
-                {
-                    ec = new ECPrivateKeyStructure(ecP.N.BitLength, ((DerInteger)privKey).PositiveValue);
+                    Asn1OctetString privEnc = keyInfo.PrivateKeyData;
+                    if (privEnc.GetOctets().Length == 32 || privEnc.GetOctets().Length == 64)
+                    {
+                        d = new BigInteger(1, Arrays.Reverse(privEnc.GetOctets()));
+                    }
+                    else
+                    {
+                        Asn1Object privKey = keyInfo.ParsePrivateKey();
+                        if (privKey is DerInteger derInteger)
+                        {
+                            d = derInteger.PositiveValue;
+                        }
+                        else
+                        {
+                            byte[] dVal = Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets());
+                            d = new BigInteger(1, dVal);
+                        }
+                    }
                 }
                 else
                 {
-                    ec = ECPrivateKeyStructure.GetInstance(privKey);
+                    X962Parameters x962Parameters = X962Parameters.GetInstance(p);
+
+                    if (x962Parameters.IsNamedCurve)
+                    {
+                        DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(x962Parameters.Parameters);
+                        X9ECParameters ecP = ECNamedCurveTable.GetByOid(oid);
+                        if (ecP == null)
+                            throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
+
+                        ecSpec = new ECGost3410Parameters(
+                            new ECNamedDomainParameters(oid, ecP),
+                            gostParams.PublicKeyParamSet,
+                            gostParams.DigestParamSet,
+                            gostParams.EncryptionParamSet);
+                    }
+                    else if (x962Parameters.IsImplicitlyCA)
+                    {
+                        ecSpec = null;
+                    }
+                    else
+                    {
+                        X9ECParameters ecP = X9ECParameters.GetInstance(x962Parameters.Parameters);
+
+                        ecSpec = new ECGost3410Parameters(
+                            new ECNamedDomainParameters(algOid, ecP),
+                            gostParams.PublicKeyParamSet,
+                            gostParams.DigestParamSet,
+                            gostParams.EncryptionParamSet);
+                    }
+
+                    Asn1Object privKey = keyInfo.ParsePrivateKey();
+                    if (privKey is DerInteger derD)
+                    {
+                        d = derD.Value;
+                    }
+                    else
+                    {
+                        ECPrivateKeyStructure ec = ECPrivateKeyStructure.GetInstance(privKey);
+
+                        d = ec.GetKey();
+                    }
                 }
 
-                return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet);
+                return new ECPrivateKeyParameters(
+                    d,
+                    new ECGost3410Parameters(
+                        ecSpec,
+                        gostParams.PublicKeyParamSet,
+                        gostParams.DigestParamSet,
+                        gostParams.EncryptionParamSet));
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
             {
diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs
index 78b06abc2..8cb66d6a6 100644
--- a/crypto/test/src/openssl/test/ReaderTest.cs
+++ b/crypto/test/src/openssl/test/ReaderTest.cs
@@ -3,6 +3,7 @@ using System.IO;
 
 using NUnit.Framework;
 
+using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Generators;
@@ -42,6 +43,23 @@ namespace Org.BouncyCastle.OpenSsl.Tests
             get { return "PEMReaderTest"; }
         }
 
+        [Test]
+        public void TestGost3410_2012()
+        {
+            string data =
+                "-----BEGIN PRIVATE KEY-----" +
+                "MEMCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIIBidanaO5G6Go8A" +
+                "thlDjR9rk4hij/PpjAQvXJr+zTqz" +
+                "-----END PRIVATE KEY-----";
+
+            using (var textReader = new StringReader(data))
+            {
+                var pemReader = new PemReader(textReader);
+                var pemObj = pemReader.ReadPemObject();
+                PrivateKeyFactory.CreateKey(pemObj.Content);
+            }
+        }
+
         public override void PerformTest()
         {
             IPasswordFinder pGet = new Password("secret".ToCharArray());