我正在尝试向我的远程服务器发送 https 请求,但我总是遇到以下异常:
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
起初我认为这是证书验证问题,所以我在发送请求之前添加了以下代码:
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, ssl) => true;
事实证明,甚至没有调用ServerCertificateValidationCallback
和the exception was related to 'Plain SSL' or 'SSL ciphers'。
请注意,我的远程服务器网址为https://_my_app_.herokuapp.com/_path_
。
奇怪的是,如果我将网址更改为任何其他 https 服务器,例如https://www.google.com
或https://www.facebook.com
,我就不会收到异常,请求也会成功。
看起来Unity使用的Mono实现不支持heroku的密码套件(我可以保证,因为我最近开发了一个能够连接到同一服务器的MonoTouch应用程序。)
是客户端还是服务器问题?我应该在客户端添加一些hacky代码还是应该更改服务器的配置?
答案 0 :(得分:3)
我没有完整的答案,但这不是密码问题; stacktrace显示它是一个证书验证问题,在验证签名的低级别之前会涉及回调。 OID 1.2.840.113549.1.1.11是SHA256withRSA,客户端中的安全提供程序(s?)没有处理它。您可以使用google和facebook等主流服务器,因为他们继续使用签名为SHA1withRSA的证书,正是因为SHA256 + RSA的客户端/浏览器支持尚未普及,尽管越来越普遍。 https://cabforum.org/baseline-requirements-documents/今年(2014年1月)无条件地要求RSA2048,但允许SHA1“直到SHA-256 [验证]被全球大部分依赖方使用的浏览器广泛支持。”
OTOH SHA1没有足够的安全空间,很多人都在推动SHA256,而Digicert似乎是更难推动的人之一:http://www.digicert.com/transitioning-to-sha-2.htm。我从herokuapp.com看到的证书最近发布(2014-01-21)所以这可能是一个刻意的选择“让我们提高安全性”或者只是“使用方便的东西,Digicert给了我们这个”。 FWIW我观察到id.heroku.com和www.heroku.com使用2013-10-12的SHA1 + RSA(2048)证书。如果您无法为SHA256 + RSA修改客户端并且heroku愿意,他们现在可以获得并使用SHA1 + RSA证书,但您可能仍需要稍后进行真正的修复。
关于这一点,How can I sign a file using RSA and SHA256 with .NET?表示对于(MS)使用SHA256 + RSA进行点网签名需要设置非默认加密提供程序,并且IME验证通常与签名相同。我不使用Mono或者知道是否适用相同或类似的问题,但这是我首先要看的区域。
答案 1 :(得分:3)
从Unity 4.3开始,Unity的Mono版本不支持SHA-256用于SSL证书。最好的&#34;支持SHA-1。我们使用GoDaddy(我知道,我知道)发布证书,幸运的是他们有一个网页,我们可以将证书从SHA-256重新键入到SHA-1。现在,SSL证书非常有用。
几乎不可能找到一个颁发SHA-1证书的CA,因此你必须重新修改它。
Unity的WWW类是用C ++编写的,不用单声道。这就是为什么你可以通过WWW而不是通过UnityHTTP插件连接到https的原因。
答案 2 :(得分:2)
我找不到原因,但我找到了问题的解决方案。
我正在使用UnityHTTP - 一个“基于TcpClient的HTTP库” - 来执行HTTP请求。
通过切换到Unity WWW class发送到我的heroku服务器的所有 https 请求成功。我发现当使用UnityHTTP
库时,Unity尝试在843端口上执行crossdomain.xml
验证,同时使用WWW class
在端口80上执行此类验证。
也许UnityHTTP
的实施涉及目前与heroku服务器不兼容的低级别内容,我不会进一步调查此问题,但我会在UnityHTTP
上打开一个问题无论如何,github存储库。
答案 3 :(得分:0)
sha-256(算法1.2.840.113549.1.1.11)应与Unity一起使用,自2.5.3起。 https://github.com/Unity-Technologies/mono/pull/134/files您欢迎