C#Websocket和ECDHE密码问题

时间:2019-10-03 02:34:07

标签: java c# ssl tomcat websocket

首先,我不是加密专家,所以我一直在挖掘新领域。

我有一个C#客户端,该客户端使用websocket从Tomcat中运行的Web服务获取信息。我们当前的环境如下:

运行客户端的工作站-具有.NET 4.6.2的Windows 10 Tomcat服务器-运行Tomcat 9.0.22和OpenJDK 11.0.2的Windows Server 2016(尽管我已经尝试过OpenJDK 13和相同的问题)

Tomcat已配置以下SSL配置:

<Connector port="8443" maxHttpHeaderSize="65536"
               allowUnsafeLegacyRenegotiation="false" 
               maxThreads="1000" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" connectionTimeout="20000"
               scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               SSLEnabled="true" protocol="org.apache.coyote.http11.Http11NioProtocol"
               sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation" 
               sslEnabledProtocols="TLSv1.2"
               keystoreType="Windows-ROOT" 
               keystoreFile="Running.txt" 
               ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,
                    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                    TLS_RSA_WITH_AES_128_CBC_SHA256,
                    TLS_RSA_WITH_AES_128_GCM_SHA256,
                    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
                    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                    TLS_RSA_WITH_AES_256_CBC_SHA,
                    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                    TLS_RSA_WITH_AES_256_CBC_SHA256,
                    TLS_RSA_WITH_AES_256_GCM_SHA384,
                    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
                    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                    SSL_RSA_WITH_RC4_128_MD5,
                    SSL_RSA_WITH_RC4_128_SHA,
                    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                    SSL_RSA_WITH_3DES_EDE_CBC_SHA"/>

因此,我们的证书存储在Windows信任库中。

我使用websockets的C#客户端代码如下:

WebSocketSharp.WebSocket ws = new WebSocketSharp.WebSocket(connectURL);
ws.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
ws.Connect();

并且我还尝试了基本的.NET ClientWebSocket:

ClientWebSocket newWs = new ClientWebSocket();
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                newWs.Options.AddSubProtocol("Tls12");
                try
                {
                    await newWs.ConnectAsync(new Uri(connectURL), CancellationToken.None);
                }
                catch (Exception wse)
                {
                    log.Error("Error in ClientWebSocket: " + wse.Message, wse);
                }

两个客户端(我相信WebSocketSharp只是基类的便捷包装),由于我们环境中所有计算机上都存在GPO,因此在客户端握手中仅发送ECDHE / DHE密码。

当尝试“生成服务器证书握手消息”时,我最终在SSL调试中遇到以下错误:

javax.net.ssl|ERROR|33|https-jsse-nio-443-exec-2|2019-10-02 16:56:50.058 UTC|TransportContext.java:313|Fatal (INTERNAL_ERROR): Failed to sign ecdhe parameters: RSA (
"throwable" : {
  java.security.SignatureException: Keyset does not exist

    at jdk.crypto.mscapi/sun.security.mscapi.RSASignature.signHash(Native Method)

问题是

  1. Google Chrome浏览器使用的密码完全相同(“ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030)”),并且连接完全正常
  2. 在Windows-ROOT证书之前,我们已将服务器证书(由外部CA生成)存储在Java密钥库中,如果将Tomcat指向该服务器,所有这些都可以正常工作。

所以我的问题是,这与证书的生成方式(我们现在正在使用内部CA生成证书)有关吗,也许是标志或扩展名或需要翻转的位?在我发现Google Chrome浏览器使用相同密码没有问题之前,我一直倾向于这样做。尽管C#客户端握手和Google Chrome客户端握手看起来有些不同(如果有帮助,我可以发布这些)。

我想该证书将为ECDHE / DHE握手正确配置所有内容,否则Chrome也将失败。但是事实是C#客户端对较早的证书没有问题,这使我相信证书生成中的某些问题引起了问题。

或者两者兼而有之?

当我要求系统管理员添加以下密码时 TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256

对于GPO,客户端能够很好地进行连接。

我们的程序中有几位对加密技术,证书生成等非常有信心的人,但是他们有些困惑,因此至少在我们可以看到的地方提供任何帮助都是很棒的。我相信我们可以免除允许TLS_RSA密码的要求,但是由于ECDHE / DHE握手提供了更高级别的安全性,因此很好地判断出故障发生在哪里以及如何解决它将非常好。我在这方面的知识已经用尽了。

谢谢!

0 个答案:

没有答案