it-swarm.com.de

Mono-https-Webanforderung schlägt fehl mit "Die Authentifizierung oder Entschlüsselung ist fehlgeschlagen"

Ich mache einen einfachen REST - Client, der in meinen C # -Anwendungen verwendet werden kann. In .net unter Windows Es funktioniert hervorragend mit http: // und https: // Verbindungen. In Mono 2.6.7 (auch getestet mit 2.8 mit den gleichen Ergebnissen) funktioniert auf Ubuntu 10.10 nur http: //. https: // Verbindungen lösen diese Ausnahme in der request.GetResponse () - Methode aus:

Unhandled Exception: System.Net.WebException: Error getting response stream (Write: The authentication or decryption has failed.): SendFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a
  at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates) [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
  at Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 

Ich konnte keine Lösung finden. Hat jemand eine Idee, warum dies geschieht und wie man es reparieren kann?

Auch dies schlägt nur in Mono fehl, es scheint kein Problem zu bestehen, eine Verbindung herzustellen.

hier ist der aufrufcode:

public JToken DoRequest(string path, params string[] parameters) {
    if(!path.StartsWith("/")) {
        path = "/" + path;
    }
    string fullUrl = url + path + ToQueryString(parameters);

    if(DebugUrls) Console.WriteLine("Requesting: {0}", fullUrl);

    WebRequest request = HttpWebRequest.CreateDefault(new Uri(fullUrl));
    using(WebResponse response = request.GetResponse())
    using(Stream responseStream = response.GetResponseStream()) {
        return ReadResponse(responseStream);
    }
}
66
Joel

Mono vertraut standardmäßig keinem Zertifikat. Um die vertrauenswürdigen Mozilla-Stammberechtigungen zu importieren, können Sie mozroots --import --quiet im Mono-Installationsordner ausführen, in dem sich mozroots.exe befindet

4
LiriB

Ich hatte das gleiche Problem mit Unity (das auch Mono verwendet) und diesem Beitrag hat mir geholfen, es zu lösen.

Fügen Sie einfach die folgende Zeile hinzu, bevor Sie Ihre Anfrage stellen:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

Und diese Methode:

public bool MyRemoteCertificateValidationCallback(System.Object sender,
    X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool isOk = true;
    // If there are errors in the certificate chain,
    // look at each error to determine the cause.
    if (sslPolicyErrors != SslPolicyErrors.None) {
        for (int i=0; i<chain.ChainStatus.Length; i++) {
            if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown) {
                continue;
            }
            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
            chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
            chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
            chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
            bool chainIsValid = chain.Build ((X509Certificate2)certificate);
            if (!chainIsValid) {
                isOk = false;
                break;
            }
        }
    }
    return isOk;
}
47
Ludovic Feltz

Das .NET Framework unter Windows verwendet den Windows-Zertifikatspeicher (mmc, Snap-Ins hinzufügen/entfernen, Zertifikate), um zu bestimmen, ob ein SSL-Zertifikat von einer Remote-Site akzeptiert wird. Windows wird mit einer Reihe von Root- und Intermediate Certificate Authorities (CA) geliefert. Sie werden regelmäßig von Windows Update aktualisiert. Daher vertraut Ihr .NET-Code im Allgemeinen einem Zertifikat, sofern es von einer Zertifizierungsstelle oder einem Nachkommen einer Zertifizierungsstelle im Zertifikatspeicher ausgestellt wurde (die meisten seriösen kommerziellen Zertifizierungsstellen sind enthalten). 

In Mono gibt es keinen Windows-Zertifikatspeicher. Mono hat einen eigenen Laden. Standardmäßig ist es leer (es gibt keine vertrauenswürdigen Standardzertifizierungsstellen). Sie müssen die Einträge selbst verwalten. 

Schauen Sie hier: 

Der Punkt mozroots.exe bewirkt, dass Ihre Mono-Installation alles vertraut, was Firefox nach einer Standardinstallation vertraut.

27
scottt732

Schreiben Sie diese Zeile vor der HTTP-Anfrage. das sollte funktionieren.

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });


private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        //Return true if the server certificate is ok
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        bool acceptCertificate = true;
        string msg = "The server could not be validated for the following reason(s):\r\n";

        //The server did not present a certificate
        if ((sslPolicyErrors &
             SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable)
        {
            msg = msg + "\r\n    -The server did not present a certificate.\r\n";
            acceptCertificate = false;
        }
        else
        {
            //The certificate does not match the server name
            if ((sslPolicyErrors &
                 SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
            {
                msg = msg + "\r\n    -The certificate name does not match the authenticated name.\r\n";
                acceptCertificate = false;
            }

            //There is some other problem with the certificate
            if ((sslPolicyErrors &
                 SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                foreach (X509ChainStatus item in chain.ChainStatus)
                {
                    if (item.Status != X509ChainStatusFlags.RevocationStatusUnknown &&
                        item.Status != X509ChainStatusFlags.OfflineRevocation)
                        break;

                    if (item.Status != X509ChainStatusFlags.NoError)
                    {
                        msg = msg + "\r\n    -" + item.StatusInformation;
                        acceptCertificate = false;
                    }
                }
            }
        }

        //If Validation failed, present message box
        if (acceptCertificate == false)
        {
            msg = msg + "\r\nDo you wish to override the security check?";
//          if (MessageBox.Show(msg, "Security Alert: Server could not be validated",
//                       MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                acceptCertificate = true;
        }

        return acceptCertificate;
    }
7

Ich stoße auch auf den Fehler.

Ich habe ServicePointManager.ServerCertificateValidationCallback und ServicePointManager.CertificatePolicy ausprobiert, aber immer noch nicht funktioniert.

Ich ärgere mich baue einen CURL-Wrapper. Es funktioniert gut für mein Spielzeugprojekt.

/// <summary>
/// For MONO ssl decryption failed
/// </summary>
public static string PostString(string url, string data)
{
    Process p = null;
    try
    {
        var psi = new ProcessStartInfo
        {
            FileName = "curl",
            Arguments = string.Format("-k {0} --data \"{1}\"", url, data),
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = false,
        };

        p = Process.Start(psi);

        return p.StandardOutput.ReadToEnd();
    }
    finally
    {
        if (p != null && p.HasExited == false)
            p.Kill();
    }
}
3
IlPADlI

Ich hatte das gleiche Problem ... Wenn die http-Antwort diese Ausnahme auslöst, mache ich Folgendes:

System.Diagnostics.Process.Start("mozroots","--import --quiet");

dadurch werden die fehlenden Zertifikate importiert und die Ausnahme ist nie mehr passiert.

3
harry4516

Eine andere Lösung für Unity besteht darin, den ServicePointManager einmalig zu initialisieren, um die Zertifikate immer zu akzeptieren. Das funktioniert, ist aber offensichtlich nicht sicher.

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
           delegate (object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                                   System.Security.Cryptography.X509Certificates.X509Chain chain,
                                   System.Net.Security.SslPolicyErrors sslPolicyErrors)
           {
               return true; // **** Always accept
       };
2
Erik Kalkoken

Die erste Antwort sagt es bereits: Mono unter Windows ist nicht mit irgendetwas ausgestattet, daher vertraut es zunächst keinem Zertifikat. Was soll ich tun?

Hier ist ein Nizza-Artikel über verschiedene Wege, um mit dem Problem aus Sicht des Entwicklers umzugehen: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

Kurze Zusammenfassung: Sie können entweder:

  • ignorieren Sie die Sicherheitsbedenken
  • ignoriere das problem
  • den Benutzer informieren und abbrechen
  • lassen Sie den Benutzer wissen und geben Sie ihm die Wahl, auf eigenes Risiko fortzufahren

Der obige Link enthält Codebeispiele für jeden Fall.

2
Gerhard

Sie können die Mono-TLS-Implementierung in iOS Build festlegen. Alles funktioniert wie hier beschrieben: http://massivepixel.co/blog/post/xamarin-studio-6-certificate-unknown (Mono TLS jedoch nicht Ich unterstütze neuere Versionen von TLS, aber ich habe noch nicht das Problem behoben, dass es sich um ein Problem handelt.

0
Ivan Ičin

Dieses Problem hatte ich immer noch, nachdem ich die Zertifikate gemäß der akzeptierten Antwort importiert hatte.

Ich habe festgestellt, dass Unterstützung für TLS 1.2 in Mono 4.8.0 hinzugefügt wurde , das Googles BoringSSL verwendet, und dass ich eine ältere Mono-Version als diese verwendete. Ich habe auf Mono 5.10 aktualisiert und kann jetzt eine Verbindung herstellen, ohne diese Ausnahme zu erhalten.

0
Owen Pauling