Reputation: 969
I have problems with connect C# socket client to Java socket server.
Java server ( deployed on CentOS server )
System.setProperty( "javax.net.ssl.keyStore", "/etc/ssl/servercert" );
System.setProperty( "javax.net.ssl.keyStorePassword", "pass" );
SSLServerSocket serverSocket = SSLServerSocketFactory.getDefault().createServerSocket( PORT );
SSLSocket sslSocket = serverSocket.accept();
sslSocket.startHandshake();
InputStream inputStream = socket.getInputStream();
...
servercert
is keystore containing private key and entire trust chain ( primary, intermediate, root )
C# Client ( running from my laptop - Win7 x64 )
var sock = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
sock.Connect(server, port );
NetworkStream stream = new NetworkStream(sock);
SslStream ssl = new SslStream(stream);
ssl.AuthenticateAsClient(server);
ssl.Write("test");
...
Java Client ( running from my laptop - Win7 x64 )
SSLSocket sslSocket = SSLSocketFactory.getDefault().createSocket( host, port );
sslSocket.startHandshake();
UTF8OutputStreamWriter outputStreamWriter = new UTF8OutputStreamWriter( socket.getOutputStream() );
outputStreamWriter.write( "test" );
Java Client -> Java Server - success
C# Client -> Java Server - fail
Java Server errors
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# Client errors
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)
What I am doing wrong?
edit:
I've done some tests and now I know that this is not fault of C# client, because same client can connect to any HTTPS website and exchange HTTP requests ( application doesn't crash at AuthenticateAsClient
)
Upvotes: 3
Views: 4225
Reputation: 969
I found it. The problem: incorrect keystore. I merged 2 tutorials on creating keystore. First: merge private key and entire trust chain as pem. Second: import pem to keystore. But in the result I had keystore containing only main cert. Recently I wanted to verify keystore on Windows, and I used KeyStore Explorer
. Then I realized what was wrong and made new keystore successful using this tool.
Upvotes: 3
Reputation: 471
See here: https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https
If you upgrade to a newer Oracle JDK 7 or 8, that should resolve your issue.
Upvotes: 1
Reputation: 4777
I recently had to get a Windows machine via C++/Win API talking to an Apache server over SSL, so I can sympathize. You may be missing a certificate on your Windows machine (a public key) what works with the private key on the Linux (java) machine. One thing I had to do is get WireShark and watch the transactions. If you can get the private key from your Linux machine you can provide it to WireShark and it will provide a very good (decrypted) breakdown of your packet contents. This way you can watch the transaction and see where it fails as well as the exchange of the list of cipher suites. I can tell you that sometimes the error you get back from the software stack doesn't match the error you see watching the wire protocols. It seems unlikely that they can't find a common cipher suite (there are quite a few commonly used). I suspect it is either a key (certificate) issue or a failure in the dialog during the initial exchange. WireShark is your friend.
Upvotes: 1
Reputation: 31
Doesn't "no cipher suites in common" error returned by jave server show where the problem lies? If I recall TLS protocol correctly, client first sends client hello in which it specifies possible security suites (supported). Server is supposed to pick one (based on its supported security suites) and specify it in server hello. Java server didn't find any matching security suite and threw exception instead. Why java server works with java client is because both support the same cipher suits. Try making C# server and C# client and it should work the same...
Upvotes: 1