From 9dfd5af9b7ed63a33513599ae3e874c85dea15c3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 6 Nov 2022 22:44:18 +0700 Subject: GOST 2012 private key reading - see https://github.com/bcgit/bc-csharp/issues/365 --- crypto/src/security/PrivateKeyFactory.cs | 96 +++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 13 deletions(-) (limited to 'crypto/src/security/PrivateKeyFactory.cs') 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)) { -- cgit 1.4.1