ImportPkcs8PrivateKey and ImportRSAPrivateKey alternative in .net framework

Viewed 5765

in .net core 3.1 I am using ImportPkcs8PrivateKey and ImportRSAPrivateKey for some RSA private Key import as per following function

 private RSA RsaKeyAsPerContent()
        {
            //https://csfieldguide.org.nz/en/interactives/rsa-key-generator/
            //https://travistidwell.com/jsencrypt/demo/
            RSA rSA = RSA.Create();
            string privateKeyContent = "...."
            bool isPkcsprivateKey = privateKeyContent.Contains("BEGIN PRIVATE KEY");
            if (isPkcsprivateKey)
            {
                var privateKey = privateKeyContent.Replace("-----BEGIN PRIVATE KEY-----", string.Empty).Replace("-----END PRIVATE KEY-----", string.Empty);
                privateKey = privateKey.Replace(Environment.NewLine, string.Empty);
                var privateKeyBytes = Convert.FromBase64String(privateKey);
                rSA.ImportPkcs8PrivateKey(privateKeyBytes, out int _);
            }
            else
            {
                var privateKey = privateKeyContent.Replace("-----BEGIN RSA PRIVATE KEY-----", string.Empty).Replace("-----END RSA PRIVATE KEY-----", string.Empty);
                privateKey = privateKey.Replace(Environment.NewLine, string.Empty);
                var privateKeyBytes = Convert.FromBase64String(privateKey);
                rSA.ImportRSAPrivateKey(privateKeyBytes, out int _);
            }
            return rSA;
        }

now I need same import functionality in traditional .net framework version 4.6/4.7 but it is not available Any idea how can i do it in .net framework

2 Answers

You can try the following. It has been tested on .net framework 4.8 and it uses a 3rd party package "BouncyCastle.Crypto".

   public static RSACryptoServiceProvider ImportPrivateKey(string pem) {
        PemReader pr = new PemReader(new StringReader(pem));
        AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
        RSAParameters rsaParams = 
        DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);

        RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
        csp.ImportParameters(rsaParams);
        return csp;
    }

You can refer to https://gist.github.com/ststeiger/f4b29a140b1e3fd618679f89b7f3ff4a for more details.

Following is been used in .net framework 4.6

 private static RSA RsaKeyAsPerContent()
        {
            RSA rSA = RSA.Create();

            string privateKeyFromConfig = ConfigurationManager.AppSettings["privateKey"];
            rSA.ImportParameters(ImportPrivateKey(privateKeyFromConfig));
            return rSA;
        }

        public static RSAParameters ImportPrivateKey(string pem)
        {
            PemReader pr = new PemReader(new StringReader(pem));
            RsaPrivateCrtKeyParameters privKey = (RsaPrivateCrtKeyParameters)pr.ReadObject();
            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;
        }

        private static byte[] ConvertRSAParametersField(BigInteger n, int size)
        {
            byte[] bs = n.ToByteArrayUnsigned();
            if (bs.Length == size)
                return bs;
            if (bs.Length > size)
                throw new ArgumentException("Specified size too small", "size");
            byte[] padded = new byte[size];
            Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
            return padded;
        }
Related