Windows 私密金鑰存留期已簡化
當工作負載在 Windows 上載入 PKCS#12/PFX 時,如果沒有設定 PersistKeySet 或 EphemeralKeySet 儲存選項時,.NET 將決定何時不再需要私鑰並應該將其清除。 在舊版的 .NET (以及 .NET Framework) 中,使用了兩組不同的邏輯。 在 .NET 9 中,只使用一組邏輯。
先前的行為
在以前,當從 PKCS#12/PFX 載入憑證 (及其私鑰) 並使用 new X509Certificate2(pfx, password, flags)
時,載入的憑證代表私鑰的存留期。 當此憑證物件被處置時 (或在垃圾回收時未處置而最終被回收時),相關聯的私鑰也會被刪除。 共用擁有權或擁有權轉移不會發生。
當從 PKCS#12/PFX 載入憑證 (及其私鑰) 並使用 X509Certificate2Collection.Import(pfx, password, flags)
時,每個包含私鑰的載入憑證都會追踪其存留期,就像單一憑證載入一樣。 但是,除此之外,還會在憑證的原生複本上放置一個標記,以指示所有複本也應追蹤私鑰存留期。 如果基於相同的基礎 PCERT_CONTEXT
值建立第二個 X509Certificate2 物件,那麼無論哪個複本首先被處置 (或最終被回收),都會從另一個複本下方清除私鑰。
以下的程式碼失敗 (無論是使用 CryptographicException 還是 NullReferenceException),因為私鑰已刪除:
X509Certificate2Collection coll = new X509Certificate2Collection(pfx, password, X509KeyStorageFlags.DefaultKeySet);
X509Certificate2Collection coll2 = coll.Find(X509FindType.FindBySubjectName, "", false);
coll2 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
using (RSA key = coll[0].GetRSAPrivateKey())
{
key.SignData(pfx, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
}
新的行為
從 .NET 9 開始,存留期一律與直接從 PKCS#12/PFX 載入產生的 X509Certificate2 執行個體相關聯。
在先前行為一節中的相同代碼片段現在成功執行。
導入的版本
.NET 9 預覽 7
中斷性變更的類型
此變更為行為變更。
變更原因
大部分載入 PKCS#12/PFX 的工作負載使用單一憑證載入方法,並理解與該方法相關聯的存留期機制。 集合載入的機制經常讓人感到意外,有時還會導致金鑰被過早清除。
建議的動作
如果你了解集合載入存留期管理,並依賴在複本上呼叫Dispose
來造成金鑰清除,請確保你也 (或改為) 在原始載入的物件上呼叫 Dispose
。