- Home /
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?
Answer by eduardocoelho · Feb 14, 2014 at 04:57 PM
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.
Answer by Fragmental · Aug 05, 2014 at 04:56 PM
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.
Answer by masterton · Apr 24, 2014 at 05:28 PM
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)