Search code examples
c#x509certificate2

How to pair a ECDSA public key to it's private key


I've created an ECDSA CSR using certreq, now I want to import the certificate into my local store and pair it with the private key. I can import RSA public keys and pair them up no problem, and can import ECDSA certificates but they lack their private key...

I've looked into all kinds of methods and properties on every class I could see - None of them seem to have a straightforward way to "set" the private key when it's ECDsa - One promising method is the "ECDsaCertificateExtensions.CopyWithPrivateKey" method - but this shows up as not having a definition, and I'd rather not force people using this to download other versions of .net, etc. ( I'm using Windows 10 )

certificate.PrivateKey = foundCSR.PrivateKey;

Works just fine for setting RSA private keys once I've found the CSR within the system. Trying that when it's an ECDsa key throws an error "Only asymmetric keys that implement ICspAsymmetricAlgorithm are supported"

Trying to get this key into a RSACryptoProvider blob is no good because it's not RSA-based (I'm assuming) - GetECDsaPrivateKey method only gets that key - is there an equivalent to SetECDsaPrivateKey?

( I'd also be open to using other ways to get the functionality of certreq -accept - This is basically the goal, import certificate, pair it to it's private key, delete csr )


Solution

  • CopyWithPrivateKey is the only built-in way. It comes with .NET Framework 4.7.2, which is built in to Windows 10 1803+.

    The main alternative, to keep your dependencies low, is to P/Invoke CertGetCertificateContextProperty (and CertSetCertificateContextProperty) to copy over the CERT_KEY_PROV_INFO_PROP_ID property. This is less safe than using CopyWithPrivateKey, because it doesn't check that the keys match or that the target cert didn't already have a property that's being overwritten. It also doesn't work for ephemeral keys.

    The second alternative is to copy the method from .NET Core, and its preconditions.

    Personally, I'd just take 4.7.2 as a dependency.