3

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 )

wasikuss
  • 969
  • 8
  • 13
  • 1
    possible duplicate of [Java SSLHandshakeException "no cipher suites in common"](http://stackoverflow.com/questions/15076820/java-sslhandshakeexception-no-cipher-suites-in-common) – kolossus Apr 03 '15 at 13:47
  • i'ts not, because java -> java works – wasikuss Apr 03 '15 at 13:49

4 Answers4

3

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.

wasikuss
  • 969
  • 8
  • 13
1

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...

Erik
  • 31
  • 5
  • server is hosted on Linux machine, and client must be written in C#, because it is part of another application. There is any way to install missing cipher suites to support C# client? – wasikuss Apr 09 '15 at 09:46
  • Well, if this is actually the problem... using a different C# implementation of SSL would probably solve it (I don't think you can 'add' additional support to default .NET implementation without changing framework or something). Try making a quick prototype with usage of OpenSSL. – Erik Apr 09 '15 at 10:55
1

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.

Dweeberly
  • 4,668
  • 2
  • 22
  • 41
1

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.

Alex Figliolia
  • 471
  • 2
  • 5