Unity - Unable to send HTTPS request due to CryptographicException
certificate, https, mono, ssl, unity-game-engine
Solution
I could not find the reason but I found the solution for the problem.
I was using UnityHTTP - a "TcpClient-based HTTP library" - to perform HTTP requests. By switching to Unity's WWW class all https requests sent to my heroku server succeeded. I found out that when using `UnityHTTP` library Unity was attempting to perform the `crossdomain.xml` validation on the 843 port, meanwhile when using `WWW class` performed such validation on port 80.
Maybe `UnityHTTP`'s implementation deals with low-level stuff that is currently not compatible with heroku servers, I'll not further investigate this but I'll open an issue on the `UnityHTTP`'s github repository anyway.
Problem
I'm trying to send an https request to my remote server but I'm always getting the following exception: ``` Exception: System.IO.IOException: The authentication or decryption has failed. ---> System.ArgumentException: certificate ---> System.Security.Cryptography.CryptographicException: Unsupported hash algorithm: 1.2.840.113549.1.1.11 at Mono.Security.X509.X509Certificate.VerifySignature (System.Security.Cryptography.RSA rsa) [0x00000] in <filename unknown>:0 at Mono.Security.X509.X509Certificate.VerifySignature (System.Security.Cryptography.AsymmetricAlgorithm aa) [0x00000] in <filename unknown>:0 at System.Security.Cryptography.X509Certificates.X509Chain.IsSignedWith (System.Security.Cryptography.X509Certificates.X509Certificate2 signed, System.Security.Cryptography.AsymmetricAlgorithm pubkey) [0x00000] in <filename unknown>:0 at System.Security.Cryptography.X509Certificates.X509Chain.Process (Int32 n) [0x00000] in <filename unknown>:0 at System.Security.Cryptography.X509Certificates.X509Chain.ValidateChain (X509ChainStatusFlags flag) [0x00000] in <filename unknown>:0 at System.Security.Cryptography.X509Certificates.X509Chain.Build (System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) [0x00000] in <filename unknown>:0 --- End of inner exception stack trace --- at System.Security.Cryptography.X509Certificates.X509Chain.Build (System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) [0x00000] in <filename unknown>:0 at System.Net.Security.SslStream+<BeginAuthenticateAsClient>c__AnonStorey7.<>m__A (System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Int32[] certErrors) [0x00000] in <filename unknown>:0 at Mono.Security.Protocol.Tls.SslClientStream.OnRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0 at Mono.Security.Protocol.Tls.SslStreamBase.RaiseRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0 at Mono.Security.Protocol.Tls.SslClientStream.RaiseServerCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] certificateErrors) [0x00000] in <filename unknown>:0 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 ``` At first I thought it was a Certificate validation issue, so I added the following code before sending the request: ``` ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, ssl) => true; ``` Turns out that the `ServerCertificateValidationCallback` wasn't even being invoked and the exception was related to 'Plain SSL' or 'SSL ciphers'. Note that my remote server URL is `https://_my_app_.herokuapp.com/_path_`. Strangely enough, if I change the URL to any other https server such as `https://www.google.com` or `https://www.facebook.com` I don't get the Exception and the request succeeds. Looks like the Mono implementation used by Unity does not support heroku's cipher suites (I can guarantee that because I recently developed a MonoTouch application that was able to connect to the same server). Is it a client or server issue? Should I add some hacky code on the client side or should the server's configuration be changed?