IT Share you

Mono https 웹 요청이 "인증 또는 암호 해독에 실패했습니다."와 함께 실패

shareyou 2020. 11. 11. 20:57
반응형

Mono https 웹 요청이 "인증 또는 암호 해독에 실패했습니다."와 함께 실패


내 C # 애플리케이션에서 사용할 간단한 REST 클라이언트를 만들고 있습니다. Windows의 .net에서 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);
    }
}

Mono는 기본적으로 인증서를 신뢰하지 않습니다 mozroots --import --quiet. Mozroots.exe가있는 mono 설치 폴더에서 실행할 수있는 Mozilla 신뢰할 수있는 루트 기관을 가져옵니다.


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

Windows의 .NET Framework는 Windows 인증서 저장소 (mmc, 스냅인 추가 / 제거, 인증서)를 사용하여 원격 사이트에서 SSL 인증서를 수락할지 여부를 결정합니다. Windows에는 여러 루트 및 중간 인증 기관 (CA)이 함께 제공되며 Windows Update를 통해 주기적으로 업데이트됩니다. 따라서 .NET 코드는 일반적으로 CA 또는 인증서 저장소에있는 CA의 자손이 발급 한 인증서를 신뢰합니다 (가장 평판이 좋은 상업용 CA가 포함됨).

Mono에는 Windows 인증서 저장소가 없습니다. Mono에는 자체 상점이 있습니다. 기본적으로 비어 있습니다 (신뢰할 수있는 기본 CA가 없음). 항목을 직접 관리해야합니다.

여기를보세요 :

mozroots.exe 지점은 기본 설치 후 Firefox가 신뢰하는 모든 것을 신뢰하는 mono 설치를 유발합니다.


make request http request 전에이 줄을 작성하십시오. 이것은 작동해야합니다.

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

나도 오류가 발생합니다.

나는 tryied 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();
    }
}

나는 같은 문제가 있었다. http 응답이이 예외를 throw하면 다음을 수행합니다.

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

이것은 누락 된 인증서를 가져오고 예외가 다시 발생하지 않습니다.


The first answer says it already: Mono on anything other than Windows doesn’t come with anything so initially it doesn’t trust any certificate. So what to do?

Here is a nice article about different ways to deal with the problem from the developer’s perspective: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

Short summary: You can either:

  • ignore the security concern
  • ignore the problem
  • let the user know and abort
  • let the user know and give him/her a choice to continue at own risk

The above link comes with code examples for each case.


Another solution for Unity is to initialize the ServicePointManager once to always accept the certificates. This works but is obviously not secure.

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

You can set Mono TLS implementation in iOS Build and everything will work fine as described here: http://massivepixel.co/blog/post/xamarin-studio-6-certificate-unknown (though Mono TLS doesn't support newer versions of TLS but I haven't yet bumped on the issue that it is a problem).


I was still having this problem after importing the certificates as per the accepted answer.

I found that support for TLS 1.2 was added in Mono 4.8.0 which uses Google's BoringSSL, and that I was using a version of Mono older than this. I updated to Mono 5.10 and can now connect without receiving this exception.

참고URL : https://stackoverflow.com/questions/4926676/mono-https-webrequest-fails-with-the-authentication-or-decryption-has-failed

반응형