c# https mono webrequest

c# - La búsqueda web mono https falla con "Falló la autenticación o el descifrado"



webrequest (9)

Estoy creando un cliente REST simple para usar en mis aplicaciones C #. En .net en Windows Funciona muy bien con http: // y https: // connections. En mono 2.6.7 (también probado con 2.8 con los mismos resultados) en Ubuntu 10.10 solo funciona http: //. Las conexiones https: // arrojan esta excepción en el 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 <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

No he podido encontrar ninguna forma de arreglar esto. ¿Alguien tiene alguna idea de por qué está sucediendo esto y cómo solucionarlo?

De nuevo, esto solo falla en Mono. .Net no parece tener ningún problema para establecer una conexión.

aquí está el código de llamada:

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


.NET Framework en Windows usa el almacén de certificados de Windows (mmc, Agregar / Quitar complementos, Certificados) para determinar si acepta un certificado SSL de un sitio remoto. Windows se envía con un montón de Root y Autoridades de certificación intermedias (CA) y Windows Update las actualiza periódicamente. Como resultado, su código .NET generalmente confiará en un certificado siempre que haya sido emitido por una CA o un descendiente de una CA en el almacén de certificados (se incluyen las CA comerciales más acreditadas).

En Mono, no hay una tienda de certificados de Windows. Mono tiene su propia tienda. Por defecto, está vacío (no hay CA predeterminadas de confianza). Necesita administrar las entradas usted mismo.

Eche un vistazo aquí:

El punto mozroots.exe hará que su instalación mono confíe en todo aquello en lo que Firefox confíe después de una instalación predeterminada.


Escriba esta línea antes de realizar la solicitud http request. esto debería ser trabajo.

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


La primera respuesta ya lo dice: Mono en cualquier cosa que no sea Windows no viene con nada, por lo que inicialmente no confía en ningún certificado. ¿Entonces lo que hay que hacer?

Aquí hay un buen artículo sobre diferentes maneras de tratar el problema desde la perspectiva del desarrollador: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

Breve resumen: puede:

  • ignorar la preocupación de seguridad
  • ignorar el problema
  • deja que el usuario sepa y aborte
  • dejar que el usuario lo conozca y darle la opción de continuar bajo su propio riesgo

El enlace de arriba viene con ejemplos de código para cada caso.


Me encuentro con el error también.

Intenté ServicePointManager.ServerCertificateValidationCallback y ServicePointManager.CertificatePolicy pero aún no funcionó.

Me enojo construir un wraper cURL. Funciona bien para mi proyecto de juguete.

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


Mono no confía en ningún certificado de forma predeterminada, para importar las autoridades raíz confiables de Mozilla, puede ejecutar mozroots --import --quiet en la carpeta de instalación mono donde se encuentra mozroots.exe


Otra solución para Unity es inicializar ServicePointManager una vez para aceptar siempre los certificados. Esto funciona, pero obviamente no es 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 };



Tuve el mismo problema con Unity (que también usa mono) y esta publicación me ayudó a resolverlo.

Simplemente agregue la siguiente línea antes de hacer su pedido:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

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


Yo tuve el mismo problema. Cuando la respuesta http arroja esta excepción, entonces lo hago:

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

esto importa los certificados faltantes y la excepción nunca volvió a suceder.