SSL communication between Java and C# applications

2019-03-29 11:53发布

问题:

My goal is to make a secure communication between a Java server and client written in C#.

java server code:

  System.setProperty("javax.net.ssl.keyStore","cert/mySrvKeystore");
  System.setProperty("javax.net.ssl.keyStorePassword","myPassword");

  SSLServerSocketFactory sslserversocketfactory =
            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
  SSLServerSocket sslserversocket =  = (SSLServerSocket) sslserversocketfactory.createServerSocket(2389);

    while(true) {
    System.err.println("server w8 new connection");
     try {

            SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
            //sslsocket.startHandshake();

            in = sslsocket.getInputStream();
            out = sslsocket.getOutputStream();
            out.flush();

            String response = new String(receiveMessage());
            while (response != "end") {
                System.out.println("Server recv="+response);
                response = new String(receiveMessage());
                sendMessage(("echo="+response).getBytes());
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

and client written in c# :

        client = new TcpClient() { SendTimeout = 5000, ReceiveTimeout = 5000 };
        IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);

        client.Connect(serverEndPoint);
        client.NoDelay = true;
        Console.WriteLine("Client connected.");

        // Create an SSL stream that will close the client's stream.
        SslStream sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
        // The server name must match the name on the server certificate.
        try
        {
            sslStream.AuthenticateAsClient("someName");
        }
        catch (AuthenticationException error)
        {
            Console.WriteLine("Exception: {0}", error.Message);
            if (error.InnerException != null)
            {
                Console.WriteLine("Inner exception: {0}", error.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            client.Close();
            return;
        }

        ASCIIEncoding ascii = new ASCIIEncoding();
        SendData(ascii.GetBytes("Hello World"));     

and

    public static bool ValidateServerCertificate(
          object sender,
          X509Certificate certificate,
          X509Chain chain,
          SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        // Do not allow this client to communicate with unauthenticated servers.
        return false;
    }

and i get the following errors: in c#

 A first chance exception of type "System.Security.Authentication.AuthenticationException" occurred in System.dll
 Certificate error: RemoteCertificateChainErrors
 Exception: The remote certificate is invalid according to the validation procedure.
 Authentication failed - closing the connection.

I know that the issue can be the fact that i use different types of certificates, but i don't know how to make a standard sslServerSocket with X509Certificate in java. Can some one help me, with good example, or some advice how can i reach my goal ?

P.S. I was looking to bouncycastle library, causes it has both java, and c# implementation, but i would like to use standard libraries, and built-in functionality of the languages.

回答1:

From your example, it doesn't look like you need to generate your certificate and private key programmatically. You can generate a certificate in your server keystore with keytool:

keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com"

Or better, with the SAN extension too, if you're using Java 7's keytool:

keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com" -ext san=dns:www.example.com

Here, www.example.com is the host name as seen by the client. You can add other things in the Subject DN (dname), but make sure the CN is the host name.

Once it's generated, export your self-signed certificate using:

keytool -export myservercert.crt -alias myalias -keystore mykeystore.jks

You should then be able to import it as a trusted certificate in your Windows certificate store from use from C#.