0

I'm trying to create a java SSL socket server application that a few java SSL socket client applications will connect to. To guarantee the trustworthiness of both communication partners,

(1) the server should only accept a client connection if the client's certificate was signed with the server's private key

(2) the client should only communicate to the server if the server's certificate is contained in the client's trusted store.

Because I'm totally new to JSSE, I only managed the client application to connect to the server solely if its certificate is contained in the client's trusted store (condition 2). However, I have no clue how to achieve my 1st condition...

I would be grateful for every kind of help.

Best regards, Galveston01

Galveston01
  • 356
  • 2
  • 13
  • You need to set the accepted CA certificate in the SSL configuration of your server. Then the client will receive the list of accepted CAs during handshake – pedrofb Apr 21 '18 at 13:25
  • It is unusual or maybe even impossible for a single certIficate to be used as both a server certificate and a CA certificate, yet this is what is implied by your question. Are you sure you understand your requirement? – user207421 Apr 21 '18 at 23:24
  • Yes that is what I originally wanted, but @0xadecimal's solution turned out to be sufficient for me too. – Galveston01 Apr 22 '18 at 06:57

2 Answers2

1

If I understand your question correctly, what you're asking is how to enable two way SSL/TLS. This requires the client to validate the server cert (point 2 in your question) AND the server to validate the client cert - known as client authentication (point 1).

It sounds like you have got "regular" one way TLS working. I'm assuming that you've created and signed the server cert yourself (aka self signed cert) and this is why you have to import the server cert itself into the client truststore - there are no CA root/intermediate certs that have been used to sign it with.

To enable client authentication (point 1) you need to do two things:

  1. Ensure that the client certificate is in the server's truststore (as before, if this was not a self signed cert, then you would need to import the root/intermediate certs into the server truststore, no need to import the cert itself). Since you've already been through this process on the client side it should pose no problems.

  2. Configure JSSE on the server to enable client side auth. To do this you'll need to set the following property:

    SSLServerSocket.setNeedClientAuth(true)

Assuming that the truststore on the server contains your self signed client cert and the truststore on the client contains your self signed server cert then this should work.

If you are not using self signed certs but infact have access to test CA or are using genuinely signed cert ( no reason not to with letsencrypt) then you might want to look at the answers and comments to these SO questions:

client not sending certificate for client authentication in TLS

client auth failing for two way TLS

0xadecimal
  • 696
  • 5
  • 18
  • @Galveston01 In that case you didn't express your question correctly. This is just a generic solution to two-way SSL that you can find anywhere. There is nothing in this answer that satisfies your clearly stated requirement about the client certificate being signed with the server's private key. Instead it is about 'self-signed client cert[s]'. – user207421 Apr 22 '18 at 02:56
  • Originally I just wanted the server to sign all client certificates so no truststore on the server side is needed (because the server can decrypt the client's certificate with its own public key when the client is authorized). But I am lucky enough that it is running at all, so I decided in favour of taking the burden to put all client certificates in a trust store at the server side. So yes, he didn't understood it completely correct, but I was just lucky to have any solution at all – Galveston01 Apr 22 '18 at 06:50
  • @Galveston01 The client certificate isn't encrypted, so no decryption was ever necessary. The question you asked, which never made sense, and which you have not modified, is not addressed by this answer. – user207421 Apr 22 '18 at 11:45
0

JSSE has support for two classes KeyManagerFactory and TrustManagerFacory to support server-side and client-side authentication.

The client fills up the information of TrustManagerFactory while the server fills up the information of keyManagerFactory. Server fills up the parameter like below while connecting the client request:

final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
  kmf.init(ks, password.toCharArray());

client code for connection:

final TrustManagerFactory tmf = TrustManagerFactory.getInstance(ksAlgorithm);
tmf.init((KeyStore) null);
Benkerroum Mohamed
  • 1,867
  • 3
  • 13
  • 19
Ambuj Kumar
  • 71
  • 1
  • 6