C# 从证书存储导入的X509证书没有私钥

C# 从证书存储导入的X509证书没有私钥,c#,.net-core,certificate,x509certificate2,C#,.net Core,Certificate,X509certificate2,使用.net core 2.2,有一些简单的代码可以将带有私钥的证书导入Windows证书存储: using (var store = new X509Store(StoreName.Root,StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadWrite); store.Add(cert); store.Close(); } 还有一些简单的代码可以再次读取: using (var st

使用
.net core 2.2
,有一些简单的代码可以将带有私钥的证书导入Windows证书存储:

  using (var store = new X509Store(StoreName.Root,StoreLocation.CurrentUser))
  {
      store.Open(OpenFlags.ReadWrite);
      store.Add(cert);
      store.Close();
  }
还有一些简单的代码可以再次读取:

 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;
 }
但是,尽管证书已成功检索到certCollection中,但它的私钥为null,hasPrivateKey为false,即使在先前的
Add
调用中它们不是null和true。为什么会这样

更新:

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;
}

您的密钥将被创建为临时密钥,因此当它被添加到持久化存储时,该密钥将被丢弃

如果要将密钥持久化到存储证书中,则需要直接将其创建为持久化密钥,或者导出到PFX,然后重新导入(这是最简单的形式):


现在,可以像您所期望的那样添加
certWithPersistedKey

Windows不希望根存储中的证书具有关联的私钥(如果它们具有关联的私钥,则会有一个知道“我的存储”中私钥的副本)。在将相关的密钥知识保存到存储中时,Windows可能只是在擦除它。在第一个示例中,最好看看
cert
的来源。@Crypt32 cert只是一个内存中的X509Certificate2;使用C#创建。@bartonjs我的存储中的副本也没有私钥,如果我们只因为在我的存储中放置了CA证书而需要有效证书,则我的存储读取随后会失败。“使用C#创建”-如何创建?从带有EphemeralKeySet标志的PFX打开?使用CertificateRequest?(如果是后者,你可能没有制作一个持久化的密钥,并且临时密钥不会在存储中持久化)酷,我特别希望你能在我提问时看到我的问题,因为我读了你的其他一些SO答案和github,一切都很好。谢谢。这似乎也解决了我使用根CA证书创建中间CA证书的第二个问题。当我尝试使用中间CA证书签署最终实体证书时,他们会失败,说根CA没有密钥-需要更多的测试,但目前为止效果良好。实际上,对于第二个问题,我需要
certificate.CopyWithPrivateKey(rsa);
也一样,因为使用颁发者证书的创建方法与创建自签名证书时的情况不同。有关
CopyWithPrivateKey
如何工作的详细讨论,请参见:
// 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);