Search code examples
c#cryptographycertificatersacng

Create RSA key from RSACryptoServiceProvider?


I want to use the key I created via CSP (I use Utimaco interface 'CSP Tool'), to generate the CA certificate, I use this code (based on this answer):

var csp = new CspParameters()
{
    ProviderName = "Utimaco CryptoServer CSP",
    ProviderType = 1,
    KeyContainerName = "Default Container"
};

RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024, csp);
RSAParameters myRSA = rsaProvider.ExportParameters(false);
using (RSA parent = RSA.Create(myRSA))
using (RSA rsa = RSA.Create(2048))
{
    CertificateRequest parentReq = new CertificateRequest(
        "CN=Experimental Issuing Authority",
        parent,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);

    parentReq.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(true, false, 0, true));

    parentReq.CertificateExtensions.Add(
        new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));

    using (X509Certificate2 parentCert = parentReq.CreateSelfSigned(
        DateTimeOffset.UtcNow.AddDays(-45),
        DateTimeOffset.UtcNow.AddDays(365)))
    {
        CertificateRequest req = new CertificateRequest(
            "CN=Valid-Looking Timestamp Authority",
            rsa,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);

        req.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(false, false, 0, false));

        req.CertificateExtensions.Add(
            new X509KeyUsageExtension(
                System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.DigitalSignature |
                System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.NonRepudiation,
                false));

        req.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection
                {
        new Oid("1.3.6.1.5.5.7.3.8")
                },
                true));

        req.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(req.PublicKey, false));

        using (X509Certificate2 cert = req.Create(
            parentCert,
            DateTimeOffset.UtcNow.AddDays(-1),
            DateTimeOffset.UtcNow.AddDays(90),
            new byte[] { 1, 2, 3, 4 }))
        {
            // Do something with these certs, like export them to PFX,
            // or add them to an X509Store, or whatever.
            X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadWrite);
            store.Add(cert);
            store.Add(parentCert);
            store.Close();

        }
    }
}

It throws: System.Security.Cryptography.CryptographicException: 'Key does not exist.' at the parentReq.CreateSelfSigned(..) call.

This is the key info:

enter image description here


Solution

  •  RSAParameters myRSA = rsaProvider.ExportParameters(false);
     using (RSA parent = RSA.Create(myRSA))
    

    This makes parent be just the public key portion, which means it can't sign certificates.

    Assuming you want the CA certificate to know about its private key, just use rsaProvider instead of exporting/importing into parent. (Either RSA parent = rsaProvider; or just replace all usage of parent with rsaProvider)