A solicitação da web de https mono falha com “A autenticação ou a descriptografia falhou”

Eu estou fazendo um cliente REST simples para usar em meus aplicativos c #. No .net no Windows Funciona muito bem com conexões http: // e https: //. Em mono 2.6.7 (também testado com 2.8 com os mesmos resultados) no Ubuntu 10.10 apenas http: // works. https: // conexões lançam esta exceção no método 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 :0 at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in :0 at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in :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 :0 at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in :0 --- End of inner exception stack trace --- at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in :0 --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in :0 at System.Net.HttpWebRequest.GetResponse () [0x00000] in :0 

Não consegui encontrar uma maneira de corrigir isso. Alguém tem alguma idéia do porquê isso está acontecendo e como corrigi-lo?

Novamente, isso só falha no Mono. O Net não parece ter nenhum problema em estabelecer uma conexão.

aqui está o código de chamada:

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

O Mono não confia em nenhum certificado por padrão, para importar as autoridades raiz confiáveis ​​do Mozilla você pode executar mozroots --import --quiet na pasta de instalação mono onde o mozroots.exe está localizado

Eu tive o mesmo problema com o Unity (que também usa mono) e este post me ajudou a resolvê-lo.

Basta adicionar a seguinte linha antes de fazer sua solicitação:

 ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback; 

E esse método:

 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 

O .NET Framework no Windows usa o armazenamento de Certificados do Windows (mmc, Adicionar / Remover Snap-Ins, Certificados) para determinar se deve aceitar um certificado SSL de um site remoto. O Windows é fornecido com um grupo de Autoridades de Certificação Raiz e Intermediária (CA) e elas são atualizadas periodicamente pelo Windows Update. Como resultado, seu código .NET geralmente confiará em um certificado, desde que ele tenha sido emitido por uma autoridade de certificação ou por um descendente de uma autoridade de certificação no armazenamento de certificados (as CAs comerciais mais conceituadas estão incluídas).

No Mono, não há armazenamento de certificados do Windows. Mono tem sua própria loja. Por padrão, está vazio (não há CAs padrão confiáveis). Você precisa gerenciar as inputs sozinho.

Dê uma olhada aqui:

O ponto mozroots.exe fará com que sua instalação mono confie em tudo o que o Firefox confia após uma instalação padrão.

Escreva esta linha antes de solicitar pedido http. isso deveria ser trabalho.

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

Eu também encontro o erro.

Eu tentei ServicePointManager.ServerCertificateValidationCallback e ServicePointManager.CertificatePolicy mas ainda não funcionam.

Eu raiva. construa um wraper cURL. Funciona bem para o meu projeto de brinquedos.

 ///  /// For MONO ssl decryption failed ///  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(); } } 

Eu tive o mesmo problema. Quando a resposta http lança essa exceção, eu faço:

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

isso importa os certificados ausentes e a exceção nunca aconteceu novamente.

A primeira resposta já diz: Mono em qualquer coisa diferente do Windows não vem com nada, então inicialmente não confia em nenhum certificado. Então o que fazer?

Aqui está um bom artigo sobre diferentes maneiras de lidar com o problema do ponto de vista do desenvolvedor: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

Breve resumo: você pode:

  • ignorar a preocupação de segurança
  • ignore o problema
  • deixe o usuário saber e abortar
  • deixar o usuário saber e dar a ele / ela a escolha de continuar por sua conta e risco

O link acima vem com exemplos de código para cada caso.

Outra solução para o Unity é inicializar o ServicePointManager uma vez para sempre aceitar os certificados. Isso funciona, mas obviamente não é seguro.

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

Você pode definir a implementação do Mono TLS no iOS Build e tudo funcionará bem conforme descrito aqui: http://massivepixel.co/blog/post/xamarin-studio-6-certificate-unknown (embora o Mono TLS não ofereça suporte a versões mais recentes de TLS, mas eu ainda não encontrei o problema que é um problema).

Eu ainda estava tendo esse problema depois de importar os certificados conforme a resposta aceita.

Descobri que o suporte para o TLS 1.2 foi adicionado no Mono 4.8.0, que usa o BoringSSL do Google, e que eu estava usando uma versão do Mono mais antiga que essa. Eu atualizei para o Mono 5.10 e agora posso conectar sem receber essa exceção.