Windows 上的私鑰壽命與 2021 年 1 月 .NET Framework 安全性與品質整合

2020 年 11 月的 Windows 10 2004 及以下版本累積更新預覽版,以及 2021 年 1 月針對 .NET Framework 4.8 的安全與品質整合釋版本,發布了一項變更,以改善 X509Certificate2 憑證的清理流程。 以下,我們將進一步說明 Windows 上私鑰壽命的規定。

自 .NET Framework 2.0 以來,從 PKCS#12 PFX 檔案載入憑證及其相關私鑰有兩種不同的方式:透過 X509Certificate2 類別的成員作為一個憑證物件,或透過 X509Certificate2Collection.Import 方法載入所有憑證。

預設行為是私鑰會透過系統密碼函式庫之一載入名為) 金鑰的持久化 (,間接將檔案寫入磁碟。  大多數載入 PFX 的呼叫者只會暫時使用憑證物件,因此當 .NET 釋放與憑證相關的原生資源時,也會刪除私鑰。  這種行為的主要例外是

  1. X509KeyStorageFlags.PersistKeySet 旗標,導致檔案被寫入但未被刪除,
  2. X509KeyStorageFlags.EphemeralKetSet 旗標,導致私鑰載入記憶體時沒有備份檔案,
  3. 異常程序終止,可能發生在金鑰刪除待處理時。

違反直覺的是,兩種不同的憑證載入方式一直使用不同的機制來追蹤何時是刪除私鑰的適當時機。  透過 X509Certificate2 類別載入單一憑證時,會使用一個只對 .NET 執行時可見、且只適用於該單一物件參考的標記。  透過 X509Certificate2Collection.Import 載入 PFX 時,會使用原生憑證物件上的標記,這會導致「刪除責任」在代表同一原生憑證的受管理物件間共享。  這表示新的 X509Certificate2 (otherCert.Handle) 。如果otherCert是透過X509Certificate2Collection.Import從PFX載入,Dispose () 會導致私鑰檔案在呼叫Dispose () 時被刪除;但如果是透過任何X509Certificate2類別成員從PFX載入,則不會。  .NET 的某些內部部分會從原生憑證帳柄建立新的受管理 X509Certificate2 物件,例如 X509Chain 類別和 X509Certificate2Collection.Find 方法。  這些框架部分,以及直接或間接使用它們的部分,都可能導致金鑰過早被刪除,因為它們所建立的物件會被垃圾回收。

在 .NET Framework 4.8 初期版本中引入了一個錯誤,導致即使未指定 PersistKeySet 或 EphemeralKeySet,X509Certificate2Collection.Import 也無法套用刪除標記。 .NET 於 2021 年 1 月的安全與品質整合 中釋出此錯誤修正,以防止無意間累積遺棄的私鑰檔案。  受此修正影響的呼叫者可指定 PersistKeySet 旗標,將 4.8 RTM 行為) .NET Framework 無意間回傳至 (,但此舉會導致檔案累積,需透過自訂清理邏輯處理。

在 Windows 版 .NET Core 和 Windows 版 .NET 5+ 上的 X509Certificate2Collection.Import 與 2.0-4.7.2 (.NET Framework 4.8 .NET Framework 相同,且所有更新都套用) 。  .NET 團隊正考慮在 .NET 6 (或未來版本中) 轉向改良版設計,但此設計更新不適用於 .NET Framework、.NET Core 或 .NET 5。