Java: как добавить SSL-аутентификацию на стороне клиента

У меня есть этот код для подключения сервера к клиенту с использованием SSL, и теперь я хочу добавить проверку на стороне клиента:

(У меня есть серверное хранилище ключей (тип JCEKS) и клиентское хранилище ключей (тип JKS), сервер использует truststore (cacerts), где я импортировал оба сертификата, потому что я также хочу использовать этот доверенный сервер для проверки подлинности клиента)

Клиентский код:

System.setProperty("javax.net.ssl.trustStore", cerServer);
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);

SSLSocketFactory sslsocketfactory = (SSLSocketFactory)  SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", port);

Код сервера:

KeyStore ks = LoadKeyStore(new File(serverKeyStore), pwdKeyStore, "JCEKS");
KeyManagerFactory kmf; 
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, pwdKeyStore.toCharArray());

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(kmf.getKeyManagers(),null, null);   

SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
sslserversocket = (SSLServerSocket) ssf.createServerSocket(port);

заблаговременно за помощь.

изменить: Я добавляю этот код на стороне сервера:

System.setProperty("javax.net.ssl.trustStore", cacerts);
System.setProperty("javax.net.ssl.trustStoreType","JKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);

но если я удалю сертификат клиента в cacerts, соединение не даст мне ошибку и для этого я считаю, что это неправильно.

Ответ 1

Если вы хотите, чтобы ваша система использовала аутентификацию сертификата клиента, вам понадобится

  • сервер запрашивает (или требует) клиентский сертификат. Это делается установкой setWantClientAuth(true) на сокет сервера (или setNeedClientAuth, соответственно). Вам также понадобится сервер для рекламы CA, который он принимает, что обычно делается с помощью доверительного хранилища на сервере, который содержит CA, с помощью которого была создана цепочка клиент-сертификат (это, по-видимому, было тем, что вы сделали, установив javax.net.ssl.trustStore* на сервере).

  • клиент должен быть настроен с хранилищем ключей, содержащим клиентский сертификат (возможно, цепочка, если есть промежуточные ЦС) и его закрытый ключ. Это можно сделать, установив javax.net.ssl.keyStore* (что может повлиять на другие подключения) или с помощью KeyManagerFactory так же, как вы сделали это на стороне сервера.

Если вы используете setWantClientAuth(true), вы все равно не получите ошибку, так как сервер будет принимать соединения, у которых нет клиентского сертификата (сервер затем проверит сертификаты peer SSLSession, чтобы узнать, есть ли сертификат или нет). setNeedClientAuth(true) нарушит соединение, если клиент не предоставит сертификат.