1
votes

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.

2

2 Answers

0
votes

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.

0
votes

@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