123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- #if NET5_0_OR_GREATER
- using System.Runtime.Versioning;
- #endif
- using System.Security.Cryptography;
- using SystemX509 = System.Security.Cryptography.X509Certificates;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.X509;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Security
- {
- /// <summary>
- /// A class containing methods to interface the BouncyCastle world to the .NET Crypto world.
- /// </summary>
- public static class DotNetUtilities
- {
- /// <summary>
- /// Create an System.Security.Cryptography.X509Certificate from an X509Certificate Structure.
- /// </summary>
- /// <param name="x509Struct"></param>
- /// <returns>A System.Security.Cryptography.X509Certificate.</returns>
- public static SystemX509.X509Certificate ToX509Certificate(
- X509CertificateStructure x509Struct)
- {
- return new SystemX509.X509Certificate(x509Struct.GetDerEncoded());
- }
- public static SystemX509.X509Certificate ToX509Certificate(
- X509Certificate x509Cert)
- {
- return new SystemX509.X509Certificate(x509Cert.GetEncoded());
- }
- public static X509Certificate FromX509Certificate(
- SystemX509.X509Certificate x509Cert)
- {
- return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData());
- }
- public static AsymmetricCipherKeyPair GetDsaKeyPair(DSA dsa)
- {
- return GetDsaKeyPair(dsa.ExportParameters(true));
- }
- public static AsymmetricCipherKeyPair GetDsaKeyPair(DSAParameters dp)
- {
- DsaPublicKeyParameters pubKey = GetDsaPublicKey(dp);
- DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters(
- new BigInteger(1, dp.X),
- pubKey.Parameters);
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
- public static DsaPublicKeyParameters GetDsaPublicKey(DSA dsa)
- {
- return GetDsaPublicKey(dsa.ExportParameters(false));
- }
- public static DsaPublicKeyParameters GetDsaPublicKey(DSAParameters dp)
- {
- DsaValidationParameters validationParameters = (dp.Seed != null)
- ? new DsaValidationParameters(dp.Seed, dp.Counter)
- : null;
- DsaParameters parameters = new DsaParameters(
- new BigInteger(1, dp.P),
- new BigInteger(1, dp.Q),
- new BigInteger(1, dp.G),
- validationParameters);
- return new DsaPublicKeyParameters(
- new BigInteger(1, dp.Y),
- parameters);
- }
- #if NETCOREAPP1_0_OR_GREATER || NET47_OR_GREATER || NETSTANDARD1_6_OR_GREATER || UNITY_2021_2_OR_NEWER
- public static AsymmetricCipherKeyPair GetECDsaKeyPair(ECDsa ecDsa)
- {
- return GetECKeyPair("ECDSA", ecDsa.ExportParameters(true));
- }
- public static ECPublicKeyParameters GetECDsaPublicKey(ECDsa ecDsa)
- {
- return GetECPublicKey("ECDSA", ecDsa.ExportParameters(false));
- }
- public static AsymmetricCipherKeyPair GetECKeyPair(string algorithm, ECParameters ec)
- {
- ECPublicKeyParameters pubKey = GetECPublicKey(algorithm, ec);
- ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
- pubKey.AlgorithmName,
- new BigInteger(1, ec.D),
- pubKey.Parameters);
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
- public static ECPublicKeyParameters GetECPublicKey(string algorithm, ECParameters ec)
- {
- X9ECParameters x9 = GetX9ECParameters(ec.Curve);
- if (x9 == null)
- throw new NotSupportedException("Unrecognized curve");
- return new ECPublicKeyParameters(
- algorithm,
- GetECPoint(x9.Curve, ec.Q),
- new ECDomainParameters(x9));
- }
- private static Math.EC.ECPoint GetECPoint(Math.EC.ECCurve curve, ECPoint point)
- {
- return curve.CreatePoint(new BigInteger(1, point.X), new BigInteger(1, point.Y));
- }
- private static X9ECParameters GetX9ECParameters(ECCurve curve)
- {
- if (!curve.IsNamed)
- throw new NotSupportedException("Only named curves are supported");
- Oid oid = curve.Oid;
- if (oid != null)
- {
- string oidValue = oid.Value;
- if (oidValue != null)
- return ECKeyPairGenerator.FindECCurveByOid(new DerObjectIdentifier(oidValue));
- }
- return null;
- }
- #endif
- public static AsymmetricCipherKeyPair GetRsaKeyPair(RSA rsa)
- {
- return GetRsaKeyPair(rsa.ExportParameters(true));
- }
- public static AsymmetricCipherKeyPair GetRsaKeyPair(RSAParameters rp)
- {
- RsaKeyParameters pubKey = GetRsaPublicKey(rp);
- RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
- pubKey.Modulus,
- pubKey.Exponent,
- new BigInteger(1, rp.D),
- new BigInteger(1, rp.P),
- new BigInteger(1, rp.Q),
- new BigInteger(1, rp.DP),
- new BigInteger(1, rp.DQ),
- new BigInteger(1, rp.InverseQ));
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
- public static RsaKeyParameters GetRsaPublicKey(RSA rsa)
- {
- return GetRsaPublicKey(rsa.ExportParameters(false));
- }
- public static RsaKeyParameters GetRsaPublicKey(
- RSAParameters rp)
- {
- return new RsaKeyParameters(
- false,
- new BigInteger(1, rp.Modulus),
- new BigInteger(1, rp.Exponent));
- }
- public static AsymmetricCipherKeyPair GetKeyPair(AsymmetricAlgorithm privateKey)
- {
- if (privateKey is DSA dsa)
- return GetDsaKeyPair(dsa);
- #if NETCOREAPP1_0_OR_GREATER || NET47_OR_GREATER || NETSTANDARD1_6_OR_GREATER || UNITY_2021_2_OR_NEWER
- if (privateKey is ECDsa ecDsa)
- return GetECDsaKeyPair(ecDsa);
- #endif
- if (privateKey is RSA rsa)
- return GetRsaKeyPair(rsa);
- throw new ArgumentException("Unsupported algorithm specified", nameof(privateKey));
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaKeyParameters rsaKey)
- {
- // TODO This appears to not work for private keys (when no CRT info)
- return CreateRSAProvider(ToRSAParameters(rsaKey));
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaKeyParameters rsaKey, CspParameters csp)
- {
- // TODO This appears to not work for private keys (when no CRT info)
- return CreateRSAProvider(ToRSAParameters(rsaKey), csp);
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
- {
- return CreateRSAProvider(ToRSAParameters(privKey));
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey, CspParameters csp)
- {
- return CreateRSAProvider(ToRSAParameters(privKey), csp);
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaPrivateKeyStructure privKey)
- {
- return CreateRSAProvider(ToRSAParameters(privKey));
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- public static RSA ToRSA(RsaPrivateKeyStructure privKey, CspParameters csp)
- {
- return CreateRSAProvider(ToRSAParameters(privKey), csp);
- }
- public static RSAParameters ToRSAParameters(RsaKeyParameters rsaKey)
- {
- RSAParameters rp = new RSAParameters();
- rp.Modulus = rsaKey.Modulus.ToByteArrayUnsigned();
- if (rsaKey.IsPrivate)
- rp.D = ConvertRSAParametersField(rsaKey.Exponent, rp.Modulus.Length);
- else
- rp.Exponent = rsaKey.Exponent.ToByteArrayUnsigned();
- return rp;
- }
- public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
- {
- RSAParameters rp = new RSAParameters();
- rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
- rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
- rp.P = privKey.P.ToByteArrayUnsigned();
- rp.Q = privKey.Q.ToByteArrayUnsigned();
- rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
- rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
- rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
- rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
- return rp;
- }
- public static RSAParameters ToRSAParameters(RsaPrivateKeyStructure privKey)
- {
- RSAParameters rp = new RSAParameters();
- rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
- rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
- rp.P = privKey.Prime1.ToByteArrayUnsigned();
- rp.Q = privKey.Prime2.ToByteArrayUnsigned();
- rp.D = ConvertRSAParametersField(privKey.PrivateExponent, rp.Modulus.Length);
- rp.DP = ConvertRSAParametersField(privKey.Exponent1, rp.P.Length);
- rp.DQ = ConvertRSAParametersField(privKey.Exponent2, rp.Q.Length);
- rp.InverseQ = ConvertRSAParametersField(privKey.Coefficient, rp.Q.Length);
- return rp;
- }
- private static byte[] ConvertRSAParametersField(BigInteger n, int size)
- {
- return BigIntegers.AsUnsignedByteArray(size, n);
- }
- // TODO Why do we use CspParameters instead of just RSA.Create in methods below?
- // private static RSA CreateRSA(RSAParameters rp)
- // {
- //#if NETCOREAPP2_0_OR_GREATER || NET472_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- // return RSA.Create(rp);
- //#else
- // var rsa = RSA.Create();
- // rsa.ImportParameters(rp);
- // return rsa;
- //#endif
- // }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- private static RSACryptoServiceProvider CreateRSAProvider(RSAParameters rp)
- {
- CspParameters csp = new CspParameters();
- csp.KeyContainerName = string.Format("BouncyCastle-{0}", Guid.NewGuid());
- return CreateRSAProvider(rp, csp);
- }
- #if NET5_0_OR_GREATER
- [SupportedOSPlatform("windows")]
- #endif
- private static RSACryptoServiceProvider CreateRSAProvider(RSAParameters rp, CspParameters csp)
- {
- RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(csp);
- rsaCsp.ImportParameters(rp);
- return rsaCsp;
- }
- }
- }
- #pragma warning restore
- #endif
|