2

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 )

  • Does this help at all? Looks like there's some key storage flags: https://stackoverflow.com/questions/3625624/inserting-certificate-with-privatekey-in-root-localmachine-certificate-store – Stealth Rabbi May 18 '19 at 21:34
  • Don't think so, that looks like when I import a PFX ( public + private key ) which that and similar articles are helpful for. In this case, I want to import just a public key, and have it recognize that there's an existing private key on the machine. – Steven Hansen May 18 '19 at 21:43

1 Answers1

0

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.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • Thank you! I'll have to test this out once I get a moment, but that all makes sense. – Steven Hansen May 19 '19 at 04:16
  • Hmm. Any hints on how to see those private keys? I put a watch on the store, created a new CSR, and not seeing them in any store - Do they go somewhere different? – Steven Hansen May 19 '19 at 05:59
  • @StevenHansen if you’re creating the CSR/key via certreq there should be a self-signed cert in a store named “Request” (pretty sure it’s singular). If you’re creating it some other way then whatever that process is dictates where things go... – bartonjs May 19 '19 at 06:03