如何在C#和Java之间正确设置ssl套接字连接?

如何在C#和Java之间正确设置ssl套接字连接?,java,c#,sockets,ssl,Java,C#,Sockets,Ssl,我在将C#socket客户端连接到Java socket服务器时遇到问题 Java服务器(部署在CentOS服务器上) servercert是包含私钥和整个信任链(主、中间、根)的密钥库 C#客户端(从我的笔记本电脑运行-Win7 x64) Java客户端(从我的笔记本电脑运行-Win7 x64) Java客户端->Java服务器-成功 C#客户端->Java服务器-失败 Java服务器错误 Exception in thread "main" javax.net.ssl.SSLHandsha

我在将C#socket客户端连接到Java socket服务器时遇到问题

Java服务器(部署在CentOS服务器上)

servercert
是包含私钥和整个信任链(主、中间、根)的密钥库

C#客户端(从我的笔记本电脑运行-Win7 x64)

Java客户端(从我的笔记本电脑运行-Win7 x64)

Java客户端->Java服务器-成功

C#客户端->Java服务器-失败


Java服务器错误

Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
        at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1014)
        at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:731)
        at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:213)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
C#客户端错误

System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> System.ComponentModel.Win32Exception: The message received was unexpected or badly formatted
   --- End of inner exception stack trace ---
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost)
我做错了什么


编辑:


我做了一些测试,现在我知道这不是C#client的错,因为同一个客户端可以连接到任何HTTPS网站并交换HTTP请求(应用程序不会在
AuthenticateTaseClient
上崩溃)

jave server返回的“没有常见密码套件”错误是否显示了问题所在?若我正确地调用了TLS协议,那个么客户机首先发送客户机hello,其中它指定了可能的安全套件(受支持)。服务器应该选择一个(基于其支持的安全套件),并在服务器hello中指定它。Java服务器未找到任何匹配的安全套件,而是引发了异常。java服务器与java客户机协同工作的原因是两者都支持相同的密码套件。试着制作C#server和C#client,它的工作原理应该是一样的…

我最近不得不通过C++/Win API与Apache服务器通过SSL进行对话,这样我才能理解。您的Windows计算机上可能缺少一个证书(公钥),该证书与Linux(java)计算机上的私钥一起工作。我必须做的一件事就是获取并观看交易。如果你能从你的Linux机器上获得私钥,你可以将它提供给WireShark,它将提供一个非常好的(解密的)数据包内容分解。通过这种方式,您可以观察事务并查看它在哪里失败,以及密码套件列表的交换。我可以告诉你,有时你从软件堆栈中得到的错误与你在观看有线协议时看到的错误不匹配。他们似乎不太可能找不到通用的密码套件(有很多常用的)。我怀疑这可能是密钥(证书)问题,也可能是初始交换期间对话框中出现故障。WireShark是你的朋友

参见此处:


如果您升级到较新的Oracle JDK 7或8,应该可以解决您的问题

我找到了。问题是:密钥库不正确。我合并了两个关于创建密钥库的教程。第一:将私钥和整个信任链合并为pem。第二:将pem导入密钥库。但结果是我的密钥库只包含主证书。最近我想在Windows上验证密钥库,我使用了
密钥库资源管理器
。然后,我意识到了问题所在,并使用此工具成功创建了新的密钥库。

可能的重复不是,因为java->java worksserver托管在Linux机器上,客户端必须用C#编写,因为它是另一个应用程序的一部分。有没有办法安装缺失的密码套件来支持C#客户端?好吧,如果这真的是问题所在。。。使用不同的SSL C#实现可能会解决这个问题(我不认为您可以在不改变框架或其他东西的情况下“添加”对默认.NET实现的额外支持)。尝试使用OpenSSL制作一个快速原型。客户端安装了oracle JDK 8,服务器安装了OpenJDK 8。
SSLSocket sslSocket = SSLSocketFactory.getDefault().createSocket( host, port );
sslSocket.startHandshake();

UTF8OutputStreamWriter outputStreamWriter = new UTF8OutputStreamWriter( socket.getOutputStream() );
outputStreamWriter.write( "test" );
Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
        at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1014)
        at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:731)
        at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:213)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> System.ComponentModel.Win32Exception: The message received was unexpected or badly formatted
   --- End of inner exception stack trace ---
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost)