using System; using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.Rosstandart; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; namespace Org.BouncyCastle.Security; public sealed class PublicKeyFactory { private PublicKeyFactory() { } public static AsymmetricKeyParameter CreateKey(byte[] keyInfoData) { return CreateKey(SubjectPublicKeyInfo.GetInstance(Asn1Object.FromByteArray(keyInfoData))); } public static AsymmetricKeyParameter CreateKey(Stream inStr) { return CreateKey(SubjectPublicKeyInfo.GetInstance(Asn1Object.FromStream(inStr))); } public static AsymmetricKeyParameter CreateKey(SubjectPublicKeyInfo keyInfo) { AlgorithmIdentifier algorithmID = keyInfo.AlgorithmID; DerObjectIdentifier algorithm = algorithmID.Algorithm; if (algorithm.Equals(PkcsObjectIdentifiers.RsaEncryption) || algorithm.Equals(X509ObjectIdentifiers.IdEARsa) || algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss) || algorithm.Equals(PkcsObjectIdentifiers.IdRsaesOaep)) { RsaPublicKeyStructure instance = RsaPublicKeyStructure.GetInstance(keyInfo.GetPublicKey()); return new RsaKeyParameters(isPrivate: false, instance.Modulus, instance.PublicExponent); } if (algorithm.Equals(X9ObjectIdentifiers.DHPublicNumber)) { Asn1Sequence instance2 = Asn1Sequence.GetInstance(algorithmID.Parameters.ToAsn1Object()); DHPublicKey instance3 = DHPublicKey.GetInstance(keyInfo.GetPublicKey()); BigInteger value = instance3.Y.Value; if (IsPkcsDHParam(instance2)) { return ReadPkcsDHParam(algorithm, value, instance2); } DHDomainParameters instance4 = DHDomainParameters.GetInstance(instance2); BigInteger value2 = instance4.P.Value; BigInteger value3 = instance4.G.Value; BigInteger value4 = instance4.Q.Value; BigInteger j = null; if (instance4.J != null) { j = instance4.J.Value; } DHValidationParameters validation = null; DHValidationParms validationParms = instance4.ValidationParms; if (validationParms != null) { byte[] bytes = validationParms.Seed.GetBytes(); BigInteger value5 = validationParms.PgenCounter.Value; validation = new DHValidationParameters(bytes, value5.IntValue); } return new DHPublicKeyParameters(value, new DHParameters(value2, value3, value4, j, validation)); } if (algorithm.Equals(PkcsObjectIdentifiers.DhKeyAgreement)) { Asn1Sequence instance5 = Asn1Sequence.GetInstance(algorithmID.Parameters.ToAsn1Object()); DerInteger derInteger = (DerInteger)keyInfo.GetPublicKey(); return ReadPkcsDHParam(algorithm, derInteger.Value, instance5); } if (algorithm.Equals(OiwObjectIdentifiers.ElGamalAlgorithm)) { ElGamalParameter elGamalParameter = new ElGamalParameter(Asn1Sequence.GetInstance(algorithmID.Parameters.ToAsn1Object())); DerInteger derInteger2 = (DerInteger)keyInfo.GetPublicKey(); return new ElGamalPublicKeyParameters(derInteger2.Value, new ElGamalParameters(elGamalParameter.P, elGamalParameter.G)); } if (algorithm.Equals(X9ObjectIdentifiers.IdDsa) || algorithm.Equals(OiwObjectIdentifiers.DsaWithSha1)) { DerInteger derInteger3 = (DerInteger)keyInfo.GetPublicKey(); Asn1Encodable parameters = algorithmID.Parameters; DsaParameters parameters2 = null; if (parameters != null) { DsaParameter instance6 = DsaParameter.GetInstance(parameters.ToAsn1Object()); parameters2 = new DsaParameters(instance6.P, instance6.Q, instance6.G); } return new DsaPublicKeyParameters(derInteger3.Value, parameters2); } if (algorithm.Equals(X9ObjectIdentifiers.IdECPublicKey)) { X962Parameters x962Parameters = new X962Parameters(algorithmID.Parameters.ToAsn1Object()); X9ECParameters x9ECParameters = ((!x962Parameters.IsNamedCurve) ? new X9ECParameters((Asn1Sequence)x962Parameters.Parameters) : ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)x962Parameters.Parameters)); Asn1OctetString s = new DerOctetString(keyInfo.PublicKeyData.GetBytes()); X9ECPoint x9ECPoint = new X9ECPoint(x9ECParameters.Curve, s); ECPoint point = x9ECPoint.Point; if (x962Parameters.IsNamedCurve) { return new ECPublicKeyParameters("EC", point, (DerObjectIdentifier)x962Parameters.Parameters); } ECDomainParameters parameters3 = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N, x9ECParameters.H, x9ECParameters.GetSeed()); return new ECPublicKeyParameters(point, parameters3); } if (algorithm.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) { Gost3410PublicKeyAlgParameters gost3410PublicKeyAlgParameters = new Gost3410PublicKeyAlgParameters((Asn1Sequence)algorithmID.Parameters); Asn1OctetString asn1OctetString; try { asn1OctetString = (Asn1OctetString)keyInfo.GetPublicKey(); } catch (IOException) { throw new ArgumentException("invalid info structure in GOST3410 public key"); } byte[] octets = asn1OctetString.GetOctets(); byte[] array = new byte[32]; byte[] array2 = new byte[32]; for (int i = 0; i != array2.Length; i++) { array[i] = octets[31 - i]; } for (int k = 0; k != array.Length; k++) { array2[k] = octets[63 - k]; } ECDomainParameters byOid = ECGost3410NamedCurves.GetByOid(gost3410PublicKeyAlgParameters.PublicKeyParamSet); if (byOid == null) { return null; } ECPoint q = byOid.Curve.CreatePoint(new BigInteger(1, array), new BigInteger(1, array2)); return new ECPublicKeyParameters("ECGOST3410", q, gost3410PublicKeyAlgParameters.PublicKeyParamSet); } if (algorithm.Equals(CryptoProObjectIdentifiers.GostR3410x94)) { Gost3410PublicKeyAlgParameters gost3410PublicKeyAlgParameters2 = new Gost3410PublicKeyAlgParameters((Asn1Sequence)algorithmID.Parameters); DerOctetString derOctetString; try { derOctetString = (DerOctetString)keyInfo.GetPublicKey(); } catch (IOException) { throw new ArgumentException("invalid info structure in GOST3410 public key"); } byte[] octets2 = derOctetString.GetOctets(); byte[] array3 = new byte[octets2.Length]; for (int l = 0; l != octets2.Length; l++) { array3[l] = octets2[octets2.Length - 1 - l]; } BigInteger y = new BigInteger(1, array3); return new Gost3410PublicKeyParameters(y, gost3410PublicKeyAlgParameters2.PublicKeyParamSet); } if (algorithm.Equals(EdECObjectIdentifiers.id_X25519)) { return new X25519PublicKeyParameters(GetRawKey(keyInfo, X25519PublicKeyParameters.KeySize), 0); } if (algorithm.Equals(EdECObjectIdentifiers.id_X448)) { return new X448PublicKeyParameters(GetRawKey(keyInfo, X448PublicKeyParameters.KeySize), 0); } if (algorithm.Equals(EdECObjectIdentifiers.id_Ed25519)) { return new Ed25519PublicKeyParameters(GetRawKey(keyInfo, Ed25519PublicKeyParameters.KeySize), 0); } if (algorithm.Equals(EdECObjectIdentifiers.id_Ed448)) { return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0); } if (algorithm.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) || algorithm.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)) { byte[] str = ((DerOctetString)Asn1Object.FromByteArray(keyInfo.PublicKeyData.GetOctets())).str; int num = 32; if (algorithm.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)) { num = 64; } int num2 = 2 * num; byte[] array4 = new byte[1 + num2]; array4[0] = 4; for (int m = 1; m <= num; m++) { array4[m] = str[num - m]; array4[m + num] = str[num2 - m]; } Gost3410PublicKeyAlgParameters instance7 = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters); ECGost3410Parameters eCGost3410Parameters = new ECGost3410Parameters(new ECNamedDomainParameters(instance7.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(instance7.PublicKeyParamSet)), instance7.PublicKeyParamSet, instance7.DigestParamSet, instance7.EncryptionParamSet); return new ECPublicKeyParameters(eCGost3410Parameters.Curve.DecodePoint(array4), eCGost3410Parameters); } throw new SecurityUtilityException("algorithm identifier in public key not recognised: " + algorithm); } private static byte[] GetRawKey(SubjectPublicKeyInfo keyInfo, int expectedSize) { byte[] octets = keyInfo.PublicKeyData.GetOctets(); if (expectedSize != octets.Length) { throw new SecurityUtilityException("public key encoding has incorrect length"); } return octets; } private static bool IsPkcsDHParam(Asn1Sequence seq) { if (seq.Count == 2) { return true; } if (seq.Count > 3) { return false; } DerInteger instance = DerInteger.GetInstance(seq[2]); DerInteger instance2 = DerInteger.GetInstance(seq[0]); return instance.Value.CompareTo(BigInteger.ValueOf(instance2.Value.BitLength)) <= 0; } private static DHPublicKeyParameters ReadPkcsDHParam(DerObjectIdentifier algOid, BigInteger y, Asn1Sequence seq) { DHParameter dHParameter = new DHParameter(seq); int l = dHParameter.L?.IntValue ?? 0; DHParameters parameters = new DHParameters(dHParameter.P, dHParameter.G, null, l); return new DHPublicKeyParameters(y, parameters, algOid); } }