Διάρκεια ζωής ιδιωτικού κλειδιού στα Windows και συνάθροιση ενημερώσεων ασφάλειας και ποιότητας .NET Framework Ιανουαρίου 2021

Η προεπισκόπηση συγκεντρωτικών ενημερώσεων του Νοεμβρίου 2020 για Windows 10 έκδοση 2004 και παλαιότερες, καθώς και η έκδοση Συνάθροισης ενημερώσεων ασφαλείας και ποιότητας Ιανουαρίου 2021 για την .NET Framework 4.8 κυκλοφόρησαν μια αλλαγή για τη βελτίωση της διαδικασίας εκκαθάρισης για τα πιστοποιητικά X509Certificate2. Παρακάτω, παρέχουμε πρόσθετες διευκρινίσεις σχετικά με τη διάρκεια ζωής ενός ιδιωτικού κλειδιού στα Windows.

Από το .NET Framework 2.0 υπάρχουν δύο διαφορετικοί τρόποι για να φορτώσετε ένα πιστοποιητικό και το σχετικό ιδιωτικό κλειδί του από ένα αρχείο PKCS#12 PFX: ως ένα αντικείμενο πιστοποιητικού μέσω μελών στην κλάση X509Certificate2 ή ως όλα τα πιστοποιητικά που υπάρχουν στο PFX μέσω των μεθόδων X509Certificate2Collection.Import.

Η προεπιλεγμένη συμπεριφορά είναι ότι το ιδιωτικό κλειδί φορτώνεται σε ένα μόνιμο (όνομα) κλειδί μέσω μίας από τις βιβλιοθήκες κρυπτογράφησης του συστήματος, η οποία εγγράφει έμμεσα ένα αρχείο στο δίσκο.  Οι περισσότεροι καλούντες που φορτώνουν ένα PFX χρησιμοποιούν μόνο προσωρινά το αντικείμενο πιστοποιητικού, επομένως, όταν το .NET αποδεσμεύει τους εγγενείς πόρους που σχετίζονται με το πιστοποιητικό, διαγράφει επίσης το ιδιωτικό κλειδί.  Οι κύριες εξαιρέσεις σε αυτήν τη συμπεριφορά είναι

  1. Η σημαία X509KeyStorageFlags.PersistKeySet, η οποία έχει ως αποτέλεσμα το αρχείο να εγγράφεται αλλά να μην διαγράφεται,
  2. Η σημαία X509KeyStorageFlags.EphemeralKetSet, η οποία έχει ως αποτέλεσμα τη φόρτωση του ιδιωτικού κλειδιού στη μνήμη χωρίς αρχείο υποστήριξης,
  3. Μη φυσιολογικός τερματισμός της διεργασίας, που μπορεί να συμβεί όταν εκκρεμεί διαγραφή κλειδιού.

Αντίθετα, οι δύο διαφορετικοί τρόποι φόρτωσης πιστοποιητικών χρησιμοποιούσαν πάντα διαφορετικούς μηχανισμούς παρακολούθησης όταν είναι η κατάλληλη στιγμή για τη διαγραφή του ιδιωτικού κλειδιού.  Η φόρτωση ενός μεμονωμένου πιστοποιητικού μέσω της κλάσης X509Certificate2 χρησιμοποιεί έναν δείκτη που είναι ορατός μόνο στο περιβάλλον εκτέλεσης .NET και ισχύει μόνο για αυτήν την αναφορά αντικειμένου.  Η φόρτωση ενός PFX μέσω του X509Certificate2Collection.Import χρησιμοποιεί έναν δείκτη στο αντικείμενο εγγενούς πιστοποιητικού, γεγονός που έχει ως αποτέλεσμα την κοινή χρήση της "λογοδοσίας διαγραφής" σε όλα τα διαχειριζόμενα αντικείμενα που αντιπροσωπεύουν το ίδιο εγγενές πιστοποιητικό.  Αυτό σημαίνει ότι το νέο X509Certificate2(otherCert.Handle). Η Dispose() θα προκαλέσει τη διαγραφή του αρχείου ιδιωτικού κλειδιού κατά τη διάρκεια της κλήσης προς την Dispose() αν το otherCert φορτώθηκε από PFX μέσω X509Certificate2Collection.Import, αλλά όχι αν φορτώθηκε από PFX μέσω μελών κλάσης X509Certificate2.  Ορισμένα τμήματα του .NET δημιουργούν εσωτερικά νέα διαχειριζόμενα αντικείμενα X509Certificate2 από εγγενείς δείκτες χειρισμού πιστοποιητικών, όπως η κλάση X509Chain και η μέθοδος X509Certificate2Collection.Find.  Αυτά τα τμήματα του πλαισίου και τυχόν τμήματα που τα χρησιμοποιούν άμεσα ή έμμεσα, ενδέχεται να οδηγήσουν σε πρόωρη διαγραφή κλειδιού, καθώς τα αντικείμενα που δημιουργούν συλλέγονται σκουπίδια.

Παρουσιάστηκε ένα σφάλμα στην αρχική έκδοση του .NET Framework 4.8 που είχε ως αποτέλεσμα το X509Certificate2Collection.Import να μην εφαρμόσει το δείκτη διαγραφής, ακόμα και αν δεν είχαν καθοριστεί ούτε το PersistKeySet ούτε το EphemeralKeySet. Το .NET κυκλοφόρησε μια επιδιόρθωση για αυτό το σφάλμα στη συνάθροιση ενημερώσεων ασφάλειας και ποιότητας τον Ιανουάριο του 2021 , ώστε να αποτραπεί η ακούσια συσσώρευση εγκαταλελειμμένων αρχείων ιδιωτικού κλειδιού.  Οι καλούντες που επηρεάζονται από αυτήν την επιδιόρθωση μπορούν να καθορίσουν τη σημαία PersistKeySet ώστε να επιστρέψει στην (ακούσια διαφορετική) συμπεριφορά RTM .NET Framework 4.8, αν και κάτι τέτοιο θα έχει ως αποτέλεσμα τη συσσώρευση αρχείων που πρέπει να αντιμετωπιστεί με προσαρμοσμένη λογική εκκαθάρισης.

Το X509Certificate2Collection.Import στο .NET Core για Windows και το .NET 5+ για Windows συμπεριφέρεται με τον ίδιο τρόπο όπως το .NET Framework 2.0-4.7.2 (και .NET Framework 4.8 με όλες τις ενημερώσεις εφαρμοσμένες).  Η ομάδα του .NET εξετάζει το ενδεχόμενο να μετακινηθεί σε μια βελτιωμένη σχεδίαση του .NET 6 (ή μελλοντικών εκδόσεων), αλλά αυτή η ενημέρωση σχεδίασης δεν θα ισχύει για το .NET Framework, το .NET Core ή το .NET 5.