2017-11-08 9 views
0

Haftungsausschluss: Fragen mit Titeln wie dieser sind üblich, aber keine Antwort hat mir eine Lösung geliefert, also muss ich sie trotzdem fragen (mit einem neuen Parametersatz).Konnte keinen sicheren Kanal für SSL/TLS mit der Autorität 'site.com' aufbauen

Problem

Ein Webservice-Client-Endpunkt in web.config wie folgt erklärt:

<behaviors> 
    <endpointBehaviors> 
    <behavior name="bankid"> 
     <clientCredentials> 
     <clientCertificate findValue="FP Testcert 2" 
      storeLocation="LocalMachine" 
      storeName="Root" 
      x509FindType="FindBySubjectName"/> 
     <serviceCertificate> 
      <defaultCertificate findValue="Test BankID SSL Root CA v1 Test" 
      storeLocation="LocalMachine" 
      storeName="Root" 
      x509FindType="FindBySubjectName"/> 
     <authentication certificateValidationMode="None" 
      revocationMode="NoCheck" 
      trustedStoreLocation="LocalMachine"/> 
     </serviceCertificate> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 

Die Zertifikate (Client und Server-Zertifikat) werden mit der App "Zertifikate verwalten Computer" installiert. Sie werden in einer CER-Datei (Serverzertifikat) bzw. einer PFX-Datei (Clientzertifikat) gespeichert. Sie werden beide in "Vertrauenswürdige Stammzertifizierungsstellen" gespeichert.

Erfolg

den Client Ausführen des Visual Studio Debug-Webserver (IIS Express) verwendet, ist erfolgreich.

Failure

Allerdings, wenn ich versuche, es in IIS zu laufen, erhalte ich die Fehlermeldung

nicht sicheren Kanal mit Autorität für SSL/TLS etablieren kann 'site.com'

Problemlösung Methode

ich habe versucht, eine Web-aPI-Funktion zu erstellen, die mich wissen lässt, wenn der Server fest die fraglichen Zertifikate. Es tut. Der Code sieht aus wie

[HttpGet] 
[Route("Debug/certs")] 
public CertsOutput certs() 
{ 
    var certStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine); 

    certStore.Open(OpenFlags.ReadOnly); 

    var config = System.Web.Configuration.WebConfigurationManager 
     .OpenWebConfiguration("~"); 
    var group = ServiceModelSectionGroup.GetSectionGroup(config); 
    var endPointBehaviors = group.Behaviors.EndpointBehaviors; 
    var endpointBehavior = endPointBehaviors[0]; 

    var ClientCredential = (ClientCredentialsElement) endpointBehavior[0]; 

    var clientCert = ClientCredential.ClientCertificate; 
    var serverCert = ClientCredential.ServiceCertificate.DefaultCertificate; 

    var result = new CertsOutput 
    { 
     clientCert = new CertsOutput.Cert 
     { 
      FindValue = clientCert.FindValue, 
      StoreName = clientCert.StoreName.ToString(), 
      StoreLocation = clientCert.StoreLocation.ToString(), 
      FindType = clientCert.X509FindType.ToString() 
     }, 

     serverCert = new CertsOutput.Cert 
     { 
      FindValue = serverCert.FindValue, 
      StoreName = serverCert.StoreName.ToString(), 
      StoreLocation = serverCert.StoreLocation.ToString(), 
      FindType = serverCert.X509FindType.ToString() 
     } 
    }; 

    return result; 
} 

public class CertsOutput 
{ 
    public Cert clientCert { get; set; } 
    public Cert serverCert { get; set; } 

    public class Cert 
    { 
     public string FindValue { get; set; } 
     public string StoreName { get; set; } 
     public string StoreLocation { get; set; } 
     public string FindType { get; set; } 

     public string Expiration => Certificate?.GetExpirationDateString() 
      ?? "Cant find cert"; 

     X509Certificate _certificate = null; 
     private X509Certificate Certificate 
     { 
      get 
      { 
       if (_certificate != null) 
        return _certificate; 

       StoreName storeNameEnum; 
       switch(StoreName) 
       { 
        case "My": 
         storeNameEnum = System_StoreName.My; 
         break; 
        case "Root": 
         storeNameEnum = System_StoreName.Root; 
         break; 
        default: 
         throw new Exception("Unknown store name: " + StoreName); 
       } 

       StoreLocation storeLocationEnum; 
       switch(StoreLocation) 
       { 
        case "LocalMachine": 
         storeLocationEnum = System_StoreLocation.LocalMachine; 
         break; 
        case "CurrentUser": 
         storeLocationEnum = System_StoreLocation.CurrentUser; 
         break; 
        default: 
         throw new Exception("Unknown store location: " + StoreLocation); 
       } 

       var certStore = new X509Store(storeNameEnum, storeLocationEnum); 

       certStore.Open(OpenFlags.ReadOnly); 

       var certCollection = certStore.Certificates.Find 
        (X509FindType.FindBySubjectName, FindValue, validOnly:false); 

       certStore.Close(); 

       var result = certCollection[0]; 
       _certificate = result; 

       return result; 
      } 
     } 
    } 
} 

Auch wenn ich dies auf IIS leite ich eine Ausgabe wie diese zu erhalten (mit console.log in Chrom):

output revealing that the IIS actually can use the certificates

So sind die certs sind deutlich sichtbar an den IIS, obwohl sie in "Vertrauenswürdige Stammzertifizierungsstellen" gespeichert sind. Die einzige Möglichkeit, Daten zu verfallen, die abgerufen werden könnten, ist die Verwendung des Geschäfts.

Antwort

1

Das Aktivieren des CAPI2-Anmeldeereignisprotokolls gibt Ihnen möglicherweise die Antwort, warum es Could not create SSL/TLS secure channel. CAPI2-Protokoll standardmäßig deaktiviert ist. Wenn Sie es aktivieren, versuchen Sie, die Anfrage erneut zu stellen. Es sollte einige Fehlerereignisse geben, die hilfreiche Informationen über die Ursache enthalten.

CAPI2 event log

Ich würde auch prüfen (und ändern vielleicht) einige Dinge:

  • Öffnen WCF Endpunkt in IE und prüfen Sie, ob die Website von IS vertrauenswürdig ist. Wenn es nicht herausfinden warum. Das sollten Sie als erstes tun.
  • Client-Zertifikat (pfx) sollte in LocalMachine/My (Personal) Shop platziert werden. Root-CA-Zertifikate sollten im Speicher der vertrauenswürdigen Stammzertifizierungsstellen (Sie haben dieses Recht) und Zwischenzertifizierungsstellen im Zwischenzertifizierungsstellen
  • abgelegt werden. Rechte an den privaten Schlüssel sollten dem IIS-App-Pool zugewiesen werden, unter dem der WCF-Client ausgeführt wird. Es kann mit certlm.msc Werkzeug getan werden.
  • Überprüfen Sie, ob der private Schlüssel in der Web-API-Methode verwendet werden kann. Überprüfen Sie also PrivateKey Eigenschaft, unterzeichnen Sie einige Hallo Weltdaten mit ihm usw.
+0

Wie füge ich Rechte zum privaten Schlüssel zum APP-Pool Pseudobenutzer, der certlm.msc verwendet? Ich habe das Problem jetzt mit icacls.exe gelöst, einem Tool, das ich herunterladen musste. Wenn ich stattdessen certlm.msc verwenden kann, kann ich den Workflow für zukünftige Anwendungen vereinfachen. https://github.com/EricHerlitz/Mobile-BankId-.NET-Example/issues/5 –

+0

Rechtsklick auf Zertifikat in certlm.msc Werkzeug, dann 'Alle Aufgaben-> Private Schlüssel verwalten ...'. Es öffnet sich ein Fenster wie wenn Sie Rechte an Dateien vergeben. Setzen Sie 'IIS APPPOOL \ name_of_the_apppool_your_app_runs_under' als Benutzer und klicken Sie auf OK. – pepo

Verwandte Themen