6
votes

I am in the process of learning SSL and in this process I am attempting to create an SSL connection between a .NET server with a Java client. I use a self signed certificate for this purpose. I don't want to use the standard keystore in Java so I create a custom keystore and load that instead.

I use the following steps to generate the certificate and the pfx file to use at the .NET server end.

  1. Generated a cerficiate using the following command on windows.

    makecert -r -pe -sr "localhost" -$ individual -n "CN=localhost" -sv .pvk -r localhost.cer

  2. Converted this to a .pfx so that I can load this certificate on the .NET server app.

  3. Exported the .cer file as a .pem (Base64 format).

  4. Took the .cer file (the public component of the above mentioned certificate) and created a .jks file (JavaKeyStore) to use as the java client using the following command.

    keytool \ -import \ -v \ -trustcacerts \ -alias 0 \ -file <(openssl x509 -in localhost.pem) \ -keystore mystore.jks\ -storetype JKS\ -storepass ez24get

  5. Loaded this .jks in the Java client app and initiated the connection with the following code

    FileInputStream fis = new FileInputStream("res/myjksstore.jks");
    KeyStore trusted = KeyStore.getInstance("JKS");
    trusted.load(fis, "ez24get".toCharArray());           
    
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(trusted);
    
    SSLContext context = SSLContext.getInstance("SSL");
    context.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
    
    Socket socket = context.getSocketFactory().createSocket("localhost", 443);
    
    String str = "abc123";
    
    socket.getOutputStream().write(GeneralUtil.toByta(str.length()));
    socket.getOutputStream().write(str.getBytes());
    
    socket.setKeepAlive(true);
    

But when I try to write data to the socket, I get the following error at the server end

System.ComponentModel.Win32Exception: The client and server cannot communicate, because they do not possess a common algorithm

My server code looks as follows...

X509Certificate cert = new X509Certificate("localhost.pfx", "abc123");

TcpListener listener = new TcpListener(IPAddress.Loopback, 443); listener.Start();

while (true) {

try { TcpClient tcpClient = listener.AcceptTcpClient();

  NetworkStream networkStream = tcpClient.GetStream();

  SslStream sslStream = new SslStream(networkStream);

  sslStream.AuthenticateAsServer(cert, false, SslProtocols.Default,

false);

  byte[] data1 = new byte[4];

  sslStream.Read(data1, 0, data1.Length);

  int len = BitConverter.ToInt32(data1, 0);

  String message = "Length of incoming data " +

BitConverter.ToInt32(data1, 0);

  byte[] data2 = new byte[len];

  sslStream.Read(data2, 0, data2.Length);

  message += "   Message: " + ASCIIEncoding.ASCII.GetString(data2);

  Thread.Sleep(1000);     

} catch (Exception ex)
{
} }

The exception occurs at the line

sslStream.AuthenticateAsServer(cert, false, SslProtocols.Default, false);

What could be the reason for this and how can I fix it ?

Any help would be highly appreciated.

1
Try to connect to your server with openssl and check avaliable ciphersuites. openssl s_client -connect localhost:443 -CAfile <path to cert.pem> Post please output of this command.user1516873
Did you successfully connect using the standard keystore with some variant of this code, or is this your first shot at the SSL connect?TheBlastOne
Nope.. I didn't pursue this much further because I had to let go of SSL Streams due to performance related reasons. I just implemented an RSA handshake to share a session key and then used AES encryption to handle the transport. Similar to what SSL does.Heshan Perera

1 Answers

-1
votes

SSLEngine (obtained from SSLContext) must be set to client mode (setUseClientMode)