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)