Mono https веб-запрос завершается с ошибкой «Проверка подлинности или расшифровка не удалась» - PullRequest
66 голосов
/ 08 февраля 2011

Я делаю простой REST-клиент для использования в моих приложениях C #. В .net в Windows Отлично работает с соединениями http: // и https: //. В моно 2.6.7 (также протестировано с 2.8 с такими же результатами) в Ubuntu 10.10 работает только http: //. https: // соединения выдают это исключение в методе 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 

Я не смог найти способ это исправить. У кого-нибудь есть идеи, почему это происходит и как это исправить?

Опять же, это только в Mono, .Net, похоже, не имеет проблем с установлением соединения.

вот код вызова:

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);
    }
}

Ответы [ 10 ]

47 голосов
/ 28 октября 2015

У меня была такая же проблема с Unity (которая также использует моно), и этот пост помог мне решить ее.

Просто добавьте следующую строку перед выполнением запроса:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

И этот метод:

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;
}
27 голосов
/ 22 января 2014

.NET Framework в Windows использует хранилище сертификатов Windows (mmc, Add / Remove Snap-Ins, Certificates), чтобы определить, принимать ли сертификат SSL с удаленного сайта.Windows поставляется с кучей корневых и промежуточных центров сертификации (CA), и они периодически обновляются Центром обновления Windows.В результате ваш код .NET, как правило, будет доверять сертификату при условии, что он был выдан ЦС или потомком ЦС в хранилище сертификатов (в него включены наиболее авторитетные коммерческие ЦС).

В Mono нет хранилища сертификатов Windows.У Mono есть собственный магазин.По умолчанию он пуст (нет доверенных ЦС по умолчанию).Вы должны управлять записями самостоятельно.

Посмотрите здесь:

Точка mozroots.exe заставит вашу моно установку доверять всему, что Firefox доверяет после установки по умолчанию.

7 голосов
/ 03 декабря 2014

Напишите эту строку перед запросом http.это должно быть работой.

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;
    }
4 голосов
/ 12 апреля 2018

Mono не доверяет никаким сертификатам по умолчанию, чтобы импортировать доверенные корневые полномочия Mozilla, вы можете запустить mozroots --import --quiet в папке моно установки, где находится mozroots.exe

3 голосов
/ 12 августа 2015

У меня была такая же проблема.Когда http-ответ вызывает это исключение, я делаю:

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

, это импортирует отсутствующие сертификаты, и исключение больше не происходит.

3 голосов
/ 30 мая 2015

Я тоже сталкиваюсь с ошибкой.

Я пробовал ServicePointManager.ServerCertificateValidationCallback и ServicePointManager.CertificatePolicy, но все еще не работает.

Я гнев. построить обертку cURL. Это нормально работает для моего игрушечного проекта.

/// <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();
    }
}
2 голосов
/ 20 февраля 2016

Другое решение для Unity - инициализировать ServicePointManager один раз, чтобы всегда принимать сертификаты. Это работает, но, очевидно, не безопасно.

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 голосов
/ 17 октября 2015

Первый ответ уже говорит о том, что Mono для чего-либо, кроме Windows, не поставляется ни с чем, поэтому изначально он не доверяет ни одному сертификату.Так что же делать?

Вот хорошая статья о различных способах решения проблемы с точки зрения разработчика: http://www.mono -project.com / archived / usingtrustedrootsrespectfully /

Краткое резюме: Вы можете:

  • игнорировать проблему безопасности
  • игнорировать проблему
  • сообщить пользователю и прервать
  • сообщите пользователю и дайте ему / ей выбор продолжить на свой страх и риск

Приведенная выше ссылка содержит примеры кода для каждого случая.

0 голосов
/ 26 августа 2018

У меня все еще была проблема после импорта сертификатов в соответствии с принятым ответом.

Я обнаружил, что поддержка для TLS 1.2 была добавлена ​​в Mono 4.8.0 , которая использует BoringSSL от Google, и что я использовал версию Mono старше этой. Я обновил Mono 5.10 и теперь могу подключиться без получения этого исключения.

0 голосов
/ 03 августа 2016

Вы можете установить реализацию Mono TLS в iOS Build, и все будет работать нормально, как описано здесь: http://massivepixel.co/blog/post/xamarin-studio-6-certificate-unknown (хотя Mono TLS не поддерживает более новые версии TLS, но я еще не сталкивался с проблемой, которая это проблема).

...