1

I am working on creating my own pkcs12 certificate from a given certificate data and key data. The key data is a base64encoded string. It is in pkcs1 format.

            byte[] keyData = null;
            byte[] certData = null;

            if (!string.IsNullOrWhiteSpace(clientCertificateKeyData))
            {
                keyData = Convert.FromBase64String(clientCertificateKeyData);
            }

            if (!string.IsNullOrWhiteSpace(clientCertificateData))
            {
                certData = Convert.FromBase64String(clientCertificateData);
            }

            object key;
            using (var reader = new StreamReader(new MemoryStream(keyData)))
            {
                key = new PemReader(reader).ReadObject();
                var keyPair = key as AsymmetricCipherKeyPair;
                if (keyPair != null)
                {
                    key = keyPair.Private;
                }
            }

            var rsaPrivateKeyParams = (RsaPrivateCrtKeyParameters)key;
            var rsaParameters = DotNetUtilities.ToRSAParameters(rsaPrivateKeyParams);

            var cspParams = new CspParameters
            {
                KeyContainerName = Guid.NewGuid().ToString(),
                KeyNumber = (int)KeyNumber.Exchange,
                Flags = CspProviderFlags.NoFlags
            };

            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
            rsaKey.ImportParameters(rsaParameters);

            X509Certificate2 certificate = new X509Certificate2(certData);
            certificate.PrivateKey = rsaKey;

            var base64Cert = Convert.ToBase64String(certificate.Export(X509ContentType.Pkcs12));

            return base64Cert;

I am creating a RSACryptoServiceProvider (line 131) that imports RsaParameters and which is then assigned to the certificate’s private key(line 135). I am using DotNetUtilities to create the RsaParameters currently(line 122). I wanted to know whether there was any method by which I could convert the keyData to RsaParameters using .NET libraries. AsymmetricCipherKeyPair, RsaPrivateCrtKeyParameters and DotNetUtilities are from Bouncy castle while RSACryptoServiceProvider and RsaParameters are .Net classes.

anumita
  • 11
  • 3

2 Answers2

0

If your keyData is a PKCS#8 (unencrypted) private key, then you can do the following gymnastics to get the RSACryptoServiceProvider you need to use set_PrivateKey.

using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
{
    CngExportPolicies policy = CngExportPolicies.AllowPlaintextExport;

    key2.SetProperty(
        new CngProperty(
            "Export Policy",
            BitConverter.GetBytes((int)policy),
            CngPropertyOptions.Persist));

    using (RSA rsaCng = new RSACng(cngKey))
    {
        var cspParams = new CspParameters
        {
            KeyContainerName = Guid.NewGuid().ToString(),
            KeyNumber = (int)KeyNumber.Exchange,
            Flags = CspProviderFlags.NoFlags
        };

        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
        rsaKey.ImportParameters(rsaCng.ExportParameters(true));
        ...
    }
}

Otherwise, it's really hard. See Digital signature in c# without using BouncyCastle.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • I am getting a "Error in encode or decode operation " error at the CngKey.Import function. The key data byte array is got from a base 64 string. On decoding the string i found out that the key is a RSA PkCS1 private key. Hence i think creating a cng key is not working as it does not have a pkcs1 format blob type – anumita Mar 28 '18 at 10:15
  • @anumita Ah, I read that as you had data out of a PFX, so it would already be in a PKCS8 format. Added a link to a similar question where the answer is "this is hard unless you're PKCS8 or already a PFX". – bartonjs Mar 28 '18 at 15:14
0

@bartonjs, thanks for your help! I was able to get rsa parameters using PCLCrypto

package. This package is available as a nuget package as well. It can read 5 key formats into RSAParameters. PKCS1, PKCS8, X509SubjectPublicKeyInfo, CAPI, and BCrypt are supported

anumita
  • 11
  • 3