Search code examples
c#.net-corecertificatex509certificate2

X509 certificate imported from certificate store has no private key


There's some simple code to import a certificate with a private key into the Windows Certificate store using .net core 2.2:

  using (var store = new X509Store(StoreName.Root,StoreLocation.CurrentUser))
  {
      store.Open(OpenFlags.ReadWrite);
      store.Add(cert);
      store.Close();
  }

And some just as simple code to read it back out again:

 using (var store = new X509Store(StoreName.Root,StoreLocation.CurrentUser))
 {
    store.Open(OpenFlags.ReadOnly);
    var certCollection = store.Certificates.Find(X509FindType.FindBySubjectName, commonName, validOnly);
    store.Close();
    return certCollection;
 }

However although the certificate is successfully retrieved into the certCollection, it's private key is null and hasPrivateKey is false, even though they were not null and true on the prior Add call. Why is this?

Update:

using (RSA rsa = RSA.Create(keySize)) {    
     CertificateRequest certRequest = new CertificateRequest(
         subjectName,
         rsa,
         HashAlgorithmName.SHA512,
         RSASignaturePadding.Pkcs1);

     certRequest.CertificateExtensions
         .Add(newX509SubjectKeyIdentifierExtension(certRequest.PublicKey, false));  
     return certRequest;
}

Solution

  • Your key is being created as an ephemeral key, so when it's being added to a persisted store the key is being discarded.

    If you want to persist the key into the store certificate, you either need to create it as a persisted key directly, or export to a PFX then re-import (which is the easiest form):

    // If you're planning on saving to a LocalMachine store you should also | in the
    // X509KeyStorageFlags.MachineKeySet bit.
    X509KeyStorageFlags storageFlags = X509KeyStorageFlags.PersistKeySet;
    
    X509Certificate2 certWithPersistedKey =
        new X509Certificate2(
            certWithEphemeralKey.Export(X509ContentType.Pkcs12, ""),
            "",
            storageFlags);
    

    Now certWithPersistedKey can be added like you expect.