2017-01-05 62 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