簡體   English   中英

從 azure 網站訪問證書時密鑰集不存在

[英]Keyset does not exist when accessing certificate from azure web site

當我使用以下代碼從文件系統訪問證書時,無論是在本地還是在 azure 網站上,都沒有問題:

X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
                   X509KeyStorageFlags.PersistKeySet |
                   X509KeyStorageFlags.Exportable);

但是,當我按照https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/ 上的說明使用 azure 證書存儲時,前 3 個到9 個請求,所有后續調用都在以下行失敗

var rsa = certificate.PrivateKey as RSACryptoServiceProvider;

出現錯誤“System.Security.Cryptography.CryptographicException: Keyset does not exist”,直到站點重新啟動,然后至少可以再處理 3 個請求。

我很困惑為什么它對至少 3 個和最多 9 個請求有效,然后總是因錯誤而失敗。 我將不勝感激任何建議。

從 PFX 加載時,您指定了 PersistKeySet,通常只有在您計划將證書持久保存到證書存儲時才應設置。 盡管通過將 RSACryptoServiceProvider 對象的PersistKeyInCsp標記為false ,代碼的某些方面可能會嘗試變得聰明並自行清理私鑰。

我指出這一點的原因是“密鑰集不存在”錯誤幾乎總是意味着“證書存儲被告知存在私鑰,但有人在沒有通知證書存儲的情況下刪除了它”。 最有可能的罪魁禍首是某處將PersistKeyInCsp設置為false (這意味着“刪除 Dispose/Finalize 上的密鑰文件”)。

如果您將 PersistKeyInCsp 設置為 false 但不手動處理對象,則由於終結器,您將獲得延遲清理,這將解釋為什么它是 3-9 成功而不是確定性數字。

(我也不得不指出你應該使用cert.GetRSAPrivateKey()而不是cert.PrivateKey ,因為a)它是類型安全的,b)它是調用者擁有的生命周期(你應該處理它)而不是共享/不明確的生命周期。 它使事情變得更加可預測,盡管它幾乎從不返回 RSACryptoServiceProvider,因此您不應該嘗試對其進行強制轉換)

看起來顯式處理( using關鍵字)解決了這個問題:

using (X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
                   X509KeyStorageFlags.PersistKeySet |
                   X509KeyStorageFlags.Exportable))
{
// ... use cert
}

單身人士為我工作:

  class static CertificateSingleton
  {
       private static X509Certificate2 certificate;

       public Get()
       {
            if (certificate == null) 
            {
                 byte[] certificateBytes = .....;
                 string password = .....;

                 certificate = new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
            }

            return certificate;
       }
  }

所以每次我想使用它時,我都會使用CertificatesSingleton.Get()並且這保證我每次都使用相同的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM