Okres istnienia klucza prywatnego w systemie Windows i pakiet zbiorczy zabezpieczeń i jakości platformy .NET Framework ze stycznia 2021 r.

W wersji zapoznawczej aktualizacji zbiorczej z listopada 2020 r. dla systemu Windows 10 w wersji 2004 i starszych, a także w wersji zbiorczej zabezpieczeń i jakości ze stycznia 2021 r. dla platformy .NET Framework 4.8 opublikowano zmianę usprawniającą proces oczyszczania certyfikatów X509Certificate2. Poniżej podano dodatkowe wyjaśnienia dotyczące okresu istnienia klucza prywatnego w systemie Windows.

Od wersji .NET Framework 2.0 istnieją dwa różne sposoby ładowania certyfikatu i związanego z nim klucza prywatnego z pliku PFX PKCS#12: jako jeden obiekt certyfikatu za pośrednictwem elementów członkowskich klasy X509Certificate2 lub jako wszystkie certyfikaty obecne w pliku PFX za pośrednictwem metod X509Certificate2Collection.Import.

Domyślnym zachowaniem jest to, że klucz prywatny jest ładowany do utrwalonego (nazwanego) klucza za pośrednictwem jednej z systemowych bibliotek kryptograficznych, co pośrednio zapisuje plik na dysku.  Większość obiektów wywołujących ładujących plik PFX używa obiektu certyfikatu tylko tymczasowo, więc gdy platforma .NET zwalnia zasoby natywne skojarzone z certyfikatem, usuwa również klucz prywatny.  Głównymi wyjątkami od tej reguły są

  1. Flaga X509KeyStorageFlags.PersistKeySet powodująca zapisanie pliku, ale nie jego usunięcie,
  2. Flaga X509KeyStorageFlags.EphemeralKetSet, która powoduje, że klucz prywatny jest ładowany do pamięci bez pliku kopii zapasowej,
  3. Nietypowe zakończenie procesu, które może wystąpić, gdy trwa oczekiwanie na usunięcie klucza.

Wbrew intuicji, te dwa różne sposoby ładowania certyfikatów zawsze używały różnych mechanizmów śledzenia, kiedy jest odpowiedni czas na usunięcie klucza prywatnego.  Ładowanie pojedynczego certyfikatu za pośrednictwem klasy X509Certificate2 używa znacznika, który jest widoczny tylko dla środowiska uruchomieniowego platformy .NET i ma zastosowanie tylko do tego jednego odwołania do obiektu.  Ładowanie pliku PFX za pośrednictwem X509Certificate2Collection.Import używa znacznika w natywnym obiekcie certyfikatu, co powoduje, że "odpowiedzialność za usuwanie" jest współdzielona we wszystkich zarządzanych obiektach reprezentujących ten sam certyfikat natywny.  Oznacza to, że nowy X509Certificate2(otherCert.Handle). Dispose() spowoduje wymazanie pliku klucza prywatnego podczas wywołania metody Dispose(), jeśli otherCert został załadowany z pliku PFX za pośrednictwem X509Certificate2Collection.Import, ale nie, jeśli został załadowany z pliku PFX za pośrednictwem dowolnego elementu klasy X509Certificate2.  Niektóre części platformy .NET wewnętrznie tworzą nowe zarządzane obiekty X509Certificate2 na podstawie natywnych dojść certyfikatów, takich jak klasa X509Chain i metoda X509Certificate2Collection.Find.  Te części struktury, a także wszelkie części, które bezpośrednio lub pośrednio z nich korzystają, mogą powodować przedwczesne wymazywanie klucza, ponieważ obiekty, które tworzą, są odśmiecane.

W początkowej wersji programu .NET Framework 4.8 wprowadzono błąd, który powodował, że X509Certificate2Collection.Import nie stosował znacznika usuwania, nawet jeśli nie określono ani zestawu PersistKeySet, ani EphemeralKeySet. Firma .NET wydała poprawkę dotyczącą tego błędu w pakiecie zbiorczym aktualizacji zabezpieczeń i jakości ze stycznia 2021 r ., aby zapobiec niezamierzonemu gromadzeniu porzuconych plików kluczy prywatnych.  Obiekty wywołujące, których dotyczy ta poprawka, mogą określić flagę PersistKeySet w celu przywrócenia (niezamierzenie innego) zachowania programu .NET Framework 4.8 RTM, choć spowoduje to nagromadzenie plików, które należy rozwiązać za pomocą niestandardowej logiki oczyszczania.

Plik X509Certificate2Collection.Import na platformach .NET Core dla systemu Windows i .NET 5+ dla systemu Windows działa podobnie jak program .NET Framework 2.0–4.7.2 (i program .NET Framework 4.8 ze wszystkimi zastosowanymi aktualizacjami).  Zespół platformy .NET rozważa przejście do ulepszonego projektu w programie .NET 6 (lub przyszłych wersjach), ale ta aktualizacja projektu nie będzie miała zastosowania do platformy .NET Framework, .NET Core lub .NET 5.