web-dev-qa-db-fra.com

La requête en mono https échoue avec "L'authentification ou le déchiffrement a échoué"

Je crée un client REST simple à utiliser dans mes applications C #. En .net sous Windows Cela fonctionne très bien avec les connexions http: // et https: //. En mono 2.6.7 (également testé avec 2.8 avec les mêmes résultats) sur Ubuntu 10.10, seul http: // fonctionne. Les connexions https: // lèvent cette exception sur la méthode request.GetResponse ():

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 

Je n'ai pas été en mesure de trouver un moyen de résoudre ce problème. Quelqu'un sait-il pourquoi cela se produit et comment y remédier?

Encore une fois, cela n'échoue que dans Mono, .Net ne semble pas avoir de problème pour établir une connexion.

voici le code d'appel:

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 ne fait confiance à aucun certificat par défaut. Pour importer les autorités racine de confiance de Mozilla, vous pouvez exécuter mozroots --import --quiet dans le dossier d'installation mono où se trouve mozroots.exe.

4
LiriB

J'ai eu le même problème avec Unity (qui utilise également le mono) et ce post m'a aidé à le résoudre.

Ajoutez simplement la ligne suivante avant de faire votre demande:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

Et cette méthode:

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

Le .NET Framework sous Windows utilise le magasin de certificats Windows (mmc, Ajout/Suppression de composants logiciels enfichables, Certificats) pour déterminer s'il convient d'accepter un certificat SSL d'un site distant. Windows est livré avec un ensemble d'autorités de certification racines et intermédiaires qui sont mises à jour périodiquement par Windows Update. Par conséquent, votre code .NET fera généralement confiance à un certificat s'il a été émis par une autorité de certification ou un descendant d'une autorité de certification dans le magasin de certificats (la plupart des autorités de certification commerciales réputées sont incluses). 

En Mono, il n'y a pas de magasin de certificats Windows. Mono a son propre magasin. Par défaut, il est vide (aucune autorité de certification par défaut n'est approuvée). Vous devez gérer les entrées vous-même. 

Jetez un coup d'oeil ici: 

Le point mozroots.exe obligera votre installation mono à faire confiance à tout ce que Firefox fait confiance après une installation par défaut.

27
scottt732

Écrivez cette ligne avant de faire la requête http. cela devrait être un travail.

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
Pawan Chaurasiya

Je rencontre aussi l'erreur.

J'ai essayé ServicePointManager.ServerCertificateValidationCallback et ServicePointManager.CertificatePolicy mais je ne fonctionne toujours pas.

Je suis en colère. construire un wrapper cURL. Cela fonctionne bien pour mon projet de jouet.

/// <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

J'ai eu le même problème . Lorsque la réponse http lève cette exception alors je fais:

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

cela importe les certificats manquants et l'exception ne se reproduira plus jamais.

3
harry4516

Une autre solution pour Unity consiste à initialiser ServicePointManager une fois pour toujours accepter les certificats. Cela fonctionne mais n'est évidemment pas sécurisé.

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

La première réponse le dit déjà: Mono sur toute autre chose que Windows ne vient avec rien, donc au départ, il ne fait confiance à aucun certificat. Alors que faire?

Voici un article de Nice sur les différentes manières de traiter le problème du point de vue du développeur: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

Bref résumé: Vous pouvez soit:

  • ignorer le problème de sécurité
  • ignorer le problème
  • informer l'utilisateur et annuler
  • informer l'utilisateur et lui donner le choix de continuer à ses risques et périls

Le lien ci-dessus est fourni avec des exemples de code pour chaque cas.

2
Gerhard

Vous pouvez définir la mise en œuvre Mono TLS dans iOS Build et tout fonctionnera comme décrit ici: http://massivepixel.co/blog/post/xamarin-studio-6-certificate-unknown supporte les nouvelles versions de TLS mais je n’ai pas encore remarqué le problème).

0
Ivan Ičin

J'avais toujours ce problème après avoir importé les certificats conformément à la réponse acceptée.

J'ai constaté que le support de TLS 1.2 avait été ajouté dans Mono 4.8.0 , qui utilise le fichier BoringSSL de Google , et que j'utilisais une version de Mono plus ancienne que celle-ci. J'ai mis à jour Mono 5.10 et je peux maintenant me connecter sans recevoir cette exception.

0
Owen Pauling