2016-07-19 21 views
0

Ich habe ein C#, .NET4.5.2 Client/Server-System entwickelt, das TLS/SSL zur Kommunikation verwendet. Die Zertifikate werden aus einer Datei geladen. Ich habe die Zertifikatsdateien mit 'MakeCert' erstellt, um eine .pvk- und .cer-Datei zu erstellen, dann habe ich sie mit dem Dienstprogramm 'pvk2pfx' zu einer .pfx kombiniert.X509Certificate-Konstruktor benötigt> 6 Sekunden, um für einen bestimmten Benutzer ausgeführt zu werden

Um die Zertifikate verwende ich sie mit der Überlastung durch Verwendung des X509Certificate2 Konstruktor laden im Dateipfad und das Passwort als Strings weitergeben müssen:

X509Certificate2(string filePath, string password) 

ich im Laufe der Zeit habe bemerkt, dass das Laden von Zertifikaten geworden ist sehr langsam. Ich bin mir nicht sicher, ob es ein "Ereignis" gab, das sie verlangsamt oder langsam gemacht hat, aber es dauert nun bis zu 6 Sekunden, um die PFX-Datei zu laden. Laden der CER-Datei ist kein Problem und dauert ~ 0,1 Sekunden.

Ich habe Windows 8.1 und das Problem ist nur für meine Benutzeranmeldung auf dem Laptop.

Ich schrieb den folgenden Test-App das Problem zu überprüfen:

private const string filePath = @"c:\testcert.pfx"; 
    private const string password = "testpassword"; 
    static void Main(string[] args) 
    { 
     var stopwatch = new Stopwatch(); 
     try 
     { 
      Console.WriteLine("About to create certificate. Press Enter."); 
      Console.ReadLine(); 

      stopwatch.Start(); 
      var cert = new X509Certificate(filePath, password); 
      stopwatch.Stop(); 

      Console.WriteLine(stopwatch.Elapsed); 
      Console.WriteLine("Certificate created. About to reset. Press Enter."); 
      Console.ReadLine(); 

      cert.Reset(); 

      Console.WriteLine("Certificate reset. Press Enter."); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
     Console.ReadLine(); 
    } 

ich einige Kollegen gebeten, führen Sie das Programm auf ihrem PC. Ich habe auch versucht, innerhalb einer VM zu laufen und dann einen neuen Benutzer auf meinem eigenen Laptop einzurichten. In allen Fällen lief es in ~ 0,1 Sekunden, aber für meine normale Benutzeranmeldung läuft es in> 6 Sekunden.

Zuerst rief ich nicht 'Reset()' auf dem Zertifikat an, also dachte ich, dass es irgendwo ein Problem mit einigen temporären Dateien gab, also benutzte ich procmon, um herauszufinden, was vor sich ging. Ich festgestellt, dass einige temporäre Dateien wurden im folgenden Verzeichnis erstellt werden (obwohl sie wurde aufgeräumt, wenn die Anwendung auch ohne den Anruf verlassen Zurücksetzen()):

C:\Users\<username>\AppData\Roaming\Microsoft\Crypto\RSA\<SID> 

Nur um sicherzugehen Ich habe versucht, das Löschen Dateien in diesem Verzeichnis, aber es macht keinen Unterschied.

Mit Procmon kann ich sehen, dass es zwei Lücken in der Datei/Registry-Aktivität während des Ladens des Zertifikats gibt, die in einem System nicht auftreten, wo die Last schnell ist. Die erste ist, nachdem es versucht, "dpapi.dll" zu verwenden. Die zweite ist nach einem Lesen in den folgenden 'C: \ Extend \ $ UsnJrnl: $ J: $ DATA'. DPAPI.dll ist die Schnittstelle für Windows Data Protection. Die letztere Datei ist das USN Journal für NTFS, das Dateiänderungen aufzeichnet. Ich bin kein Experte auf beiden und ich bin mir nicht sicher, ob beides relevant ist!

Ich habe dann versucht, mit API Monitor http://www.rohitab.com/apimonitor Systemaufrufe zu beobachten. Wieder bin ich kein Experte, aber ich schleppte mich durch, um zu sehen, was kurz vor den Pausen passierte. Es gibt eine Menge darin, ich verstehe nicht, dass das relevant sein kann oder nicht, und ich begrüße Kommentare dazu, um mich auf das Problem zu konzentrieren.

Der letzte Anruf vor 2 Sekunden Lücke ist ein Memcpy mit dem Stapel folgenden Aufruf:

# Module Address Offset Location 
1 RPCRT4.dll 0x74f6378b 0x2378b I_RpcSendReceive + 0x1bb 
2 RPCRT4.dll 0x74f6367b 0x2367b I_RpcSendReceive + 0xab 
3 RPCRT4.dll 0x74f594df 0x194df NdrServerInitializeNew + 0x83f 
4 RPCRT4.dll 0x74f63619 0x23619 I_RpcSendReceive + 0x49 
5 RPCRT4.dll 0x74f6398b 0x2398b NdrSendReceive + 0x2b 

Höher die potentiell interessante Linien zu sein scheinen:

# Time of Day Thread Module API Return Value Error Duration 
64922 6:38:44.348 AM 1 DPAPI.dll SystemFunction040 (0x00ac5a30, 8, RTL_ENCRYPT_OPTION_SAME_LOGON) STATUS_SUCCESS  0.0000402 
64923 6:38:44.349 AM 1 CRYPTBASE.dll RtlInitUnicodeString (0x0090e5a8, "\Device\KsecDD")   0.0000004 

64949 6:38:44.349 AM 1 RPCRT4.dll RtlInitUnicodeString (0x0090e0b0, "\RPC Control\protected_storage")   0.0000000 

ich es schwierig finden, verfolgen Sie den Callstack, aber ich denke, dass diese letztlich von einer Funktion namens CryptQueryObject kommen.

Ich habe den folgenden Artikel gefunden, der relevant sein kann, aber es ist nicht Windows8.1. Ich habe den Ordner% windir% \ Temp nur für den Fall gelöscht, aber auch nicht geholfen.

https://support.microsoft.com/en-gb/kb/931908

Ich erinnere mich an einen Artikel irgendwo zu finden, dass eine Verzögerung vorgeschlagen etwas sein könnte, von CryptQueryObject mit ActiveDirectory- ruft zu tun, aber ich kann den Link nicht finden.

ich wirklich bin auf der Suche nach:

  1. Wie mein User-Login beheben, damit es nicht 6 Sekunden dauert ein Zertifikat
  2. Wie zu laden mein Code, um sicherzustellen, OK ist, damit es nicht passieren wieder oder mit anderen Menschen mit dem System

Vielen Dank für jede Hilfe.

Antwort

0

Dieses Problem wurde jetzt gelöst und ich denke Ich verstehe warum!

Wenn Sie ein X509Certificate mit einem privaten Schlüssel laden, speichert Windows den Schlüssel in einer Datei und verschlüsselt die Datei mit 'Data Protection' (daher wurden die Aufrufe von DPAPI überwacht).

https://technet.microsoft.com/en-us/library/cc962112.aspx

Der Schlüssel verwendet, um die Datei zu verschlüsseln, wird ein 'Master Key' genannt. Es basiert auf Ihrer Benutzeranmeldung und wird erneuert, wenn Sie Ihr Benutzerpasswort ändern. Es läuft auch automatisch nach 90 Tagen ab.

%APPDATA%/Microsoft/Protect/%SID% 

Ich konnte sehen, dass mein MasterKey in der Tat war älter als 90 Tage nach bei der Suche:

http://www.passcape.com/index.php?section=docsys&cmd=details&id=28#33

Wie in dem obigen Link beschrieben, ist der Hauptschlüssel im folgende Verzeichnis gespeichert Datum der letzten Änderung für die Dateien in diesem Verzeichnis. Also, wann immer ich ein Zertifikat geladen habe, versuchte es, den privaten Schlüssel in einer verschlüsselten Datei zu speichern und bemerkte, dass der Hauptschlüssel veraltet war, also würde er versuchen, ihn zu aktualisieren.

Ich ran ProcMon, aber gestoppt Filterung für Aktivität nur aus meiner Test-App. Ich konnte dann sehen, dass eine Reihe von UDP-Anrufe zu unserem Active Directory-Server während der "Lücken" von einem Prozess namens lsass.exe gemacht wurde, die mit Sicherheit und Passwort-Updates zu tun hat (kann keinen anderen Link wegen Stack-Überlauf posten) Einschränkungen, aber leicht zu suchen).

Ich denke, dass der Vorgang des Aktualisierens des Hauptschlüssels eine Interaktion mit dem ActiveDirectory-Dienst erfordern muss.

Ich arbeite remote und Verbindung zu meinem Netzwerk über VPN. Das VPN lässt keinen Zugriff auf den ActiveDirectory-Server zu, daher denke ich, dass die Verzögerungen dadurch verursacht wurden, dass versucht wurde, auf diesen Server zuzugreifen.

Ich wartete bis zu meinem nächsten Besuch im Büro und sobald ich mit dem Netzwerk verbunden war und auf den ActiveDirectory Server zugreifen konnte, verschwand die Verzögerung beim Laden von Zertifikaten. Ich habe bestätigt, dass meine MasterKey-Dateien ebenfalls aktualisiert wurden und nicht mehr veraltet sind.

Ich erneut Laden von Zertifikaten während der Verbindung über das VPN und die Verzögerung ist immer noch weg, so scheint dies zu bestätigen, dass es in Ordnung ist, solange der Hauptschlüssel nicht veraltet ist.

Leider konnte ich mein Kennwort nicht über das VPN ändern, da dieselben Probleme nicht auf den Active Directory-Dienst zugreifen können.

Mein Problem gelöst. Ich schätze, es war wahrscheinlich ziemlich einzigartig, aber ich hoffe, dass die Details meiner Untersuchung irgendwann jemand anderem helfen!