首先,我不是加密专家,所以我一直在挖掘新领域。
我有一个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)
问题是
所以我的问题是,这与证书的生成方式(我们现在正在使用内部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握手提供了更高级别的安全性,因此很好地判断出故障发生在哪里以及如何解决它将非常好。我在这方面的知识已经用尽了。
谢谢!