Unable to send HTTPS request due to CryptographicException

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?

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.

As of Unity 4.3, Unity’s version of Mono does not support SHA-256 for SSL certs. The “best” supported is SHA-1. We had used GoDaddy (I know, I know) to issue the cert and fortunately they had a web page where we could re-key the cert from SHA-256 to SHA-1. Now the SSL cert works great.

It will be near impossible to find a CA that will issue an SHA-1 cert so you will have to re-key it.

Unity’s WWW class is written in C++ and does not go through mono. That’s why you can connect to https through WWW but not through the UnityHTTP plugin.

(replied already on StackOverflow but this is such a critical Unity issue I copied it here too)

Bug fix for this should be in 4.5.3. I submitted the pull request myself. I never tested it, though, because I don’t know how to compile mono, but hopefully it works.