2017-01-05 66 views
1

当尝试使用下面的代码来从X509Store一个X509Certificate2对象:.NET核心X509Certificate2.PrivateKey抛出NTE_BAD_KEYSET错误

private X509Certificate2 GetKey() 
    { 
     try 
     { 
      X509Store store = new X509Store("WebHosting", StoreLocation.LocalMachine); 
      store.Open(OpenFlags.ReadOnly); 
      var collection = store.Certificates.Find(X509FindType.FindBySubjectName, "xxxxxxx", true); 

      if (collection.Count == 0) 
      { 
       throw new Exception("No keys matched"); 
      } 

      if (collection.Count > 1) 
      { 
       StringBuilder sb = new StringBuilder(); 
       sb.Append("More than 1 key matched:\r\n"); 

       foreach (var cert in collection) 
       { 
        sb.Append($"{cert.SubjectName} - {cert.Thumbprint}\r\n"); 
       } 
       throw new Exception(sb.ToString()); 
      } 

      return collection[0]; 
     } 
     catch (Exception ex) 
     { 
      // something really bad happened, log it 
      Logger.LogException(ex); 
      throw; 
     } 
    } 

我顺利地拿到钥匙;但是,当试图使用key.PrivateKey获取对象中的私钥时,出现以下错误:OpenCSP failed with error code 2148073494.查找Windows错误2148073494,我得到nte_bad_keyset。看起来似乎在其他情况下出现了错误,导致了相同的错误here,但他们已经修复了这个错误。当我在控制台应用程序中运行这段代码时,它运行良好,并且在IISExpress下运行的测试环境中也能正常工作。在IIS下的生产环境中运行时,每次都会出现此错误。我试图在管理员用户的环境下运行,以确保它不是一个奇怪的权限错误,同样的事情。从我对Windows错误的理解来看,Windows是否让我知道密钥的存在,然后告诉我在那个地址没有任何东西。我为此使用了"System.Security.Cryptography.Algorithms": "4.3.0"

编辑:我应该注意到,作为我的测试的一部分,我实际上从生产环境中找到了我正在寻找的确切证书到我的测试环境,并且它装载正常。我还在生产环境中运行了控制台应用程序,提供相同的密钥,并且工作正常。

+0

证书是如何进入生产机器的?如果您使用.NET读取PFX并将其添加到证书存储区,但在加载PFX时未设置“X509KeyStorageFlags.PersistKeySet”标志,则最终会得到此行为(在密钥获得“未保留” )。 – bartonjs

+0

我不使用.NET将证书添加到商店。 PFX文件被添加到商店并通过ACME应用程序进行更新。这是一个完全独立的过程,不属于我的项目。 – Middas

+0

您确定您的IIS应用程序池用户有权访问此证书的私钥吗? –

回答

0

最终,答案是“将私钥导入证书库后删除私钥”(或者,也许可能会将Windows混淆记住密钥在哪里存在,尽管它并不实际存在)。

如果你知道它,例如,适用于一小会儿,然后停止:

> certutil -store my 
... 
================ Certificate 6 ================ 
Serial Number: 3451b93c10f9279348a949f729d1ff10 
Issuer: CN=localhost 
NotBefore: 1/26/2015 2:19 PM 
NotAfter: 1/25/2020 4:00 PM 
Subject: CN=localhost 
Signature matches Public Key 
Root Certificate: Subject matches Issuer 
Template: 
Cert Hash(sha1): 15 e3 4c d3 2d a7 54 99 a9 17 8f 17 26 25 63 25 8f 3a 94 28 
    Key Container = IIS Express Development Certificate Container 
    Unique container name: fad662b360941f26a1193357aab3c12d_1fcb2e07-cec4-4ba1-9c78-58a431e1aefd 
    Provider = Microsoft RSA SChannel Cryptographic Provider 
Encryption test passed 
CertUtil: -store command completed successfully. 

看到,它是在“微软RSA SChannel加密提供程序”,转到https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx,看到密钥文件会位于%ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeysUnique container name恰好是它将拥有的文件的名称。

因此,打开该目录,右键单击该文件。

  • 属性
  • 安全选项卡
  • 高级按钮
  • 审核选项卡
  • 编辑按钮
  • 添加按钮
  • 类型 “每个人”,推 “检查名称”,选择 “每个人” ,点击确定,点击确定。
  • 检查删除:成功。
  • 点击确定关闭所有对话框。

之后,你开始键集错误后,搜索安全日志上的文件的审核(从安全的审核事件4663)删除:

An attempt was made to access an object. 

Subject: 
    Security ID:  SOMEDOMAIN\theaccount 
    Account Name:  theaccount 
    Account Domain:  SOMEDOMAIN 
    Logon ID:  0xabcdef 

Object: 
    Object Server: Security 
    Object Type: File 
    Object Name: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\fad662b360941f26a1193357aab3c12d_1fcb2e07-cec4-4ba1-9c78-58a431e1aefd 
    Handle ID: 0xef8 

Process Information: 
    Process ID: 0xf54 
    Process Name: C:\Windows\explorer.exe 

Access Request Information: 
    Accesses: DELETE 

    Access Mask: 0x10000 

,会告诉你什么进程/用户做了删除操作...也许这足以确定出了什么问题。

你可能想要更私人密钥文件识别和审计注册程序更多;但这是我知道解释它最快的方式。

+0

我尝试了你的建议,它没有任何区别,证书周围没有单个事件日志条目。我不明白在网站无法访问密钥的同时如何删除密钥,我的测试应用程序可以。 – Middas