Search code examples
c#x509certificate2

Is there a way to get the functionality of command line certreq -accept using C#?


I'm creating a windows form application that imports certificates into the local store - What I want to be able to do is have it pair it with an existing private key when possible.

I know this is possible because I can manually use the certreq -accept command on a certificate and it pairs it just fine.

X509Certificate2 certificate = new X509Certificate2(fileName);
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadWrite);
certStore.Add(certificate);
certStore.Close();

Code works great - Just doesn't match it up to a corresponding private key, which I know exists because command line certreq -accept imports it and matches it just fine. If anyone knows how to match that functionality using code ( not running command line in the code ) I'd be grateful for any guidance.

( Side note - Getting the functionality of certutil -repairstore would also be great )


Solution

  • The flow of certreq -accept is:

    • Open the Request store (e.g. new X509Store("Request", StoreLocation.LocalMachine))
    • Find the self-signed certificate which used the same public key as the signed certificate (the cert there was created by certreq)
    • Copy the private key to the new certificate (e.g. var withKey = newCert.CopyWithPrivateKey(requestCert.GetRSAPrivateKey());)
    • Add the withKey certificate to the My store (CurrentUser, or LocalMachine, whichever one matched where the key and self-signed cert was)
    • Remove requestCert from the Request store.

    All of which are solvable in C#. For "same public key" the easiest is to compare the Oid, EncodedKeyValue, and EncodedParameters properties of newCert.PublicKey and requestCert.PublicKey.