没有密钥库的 TLS 连接

TLS Connection with no Keystore

我很困惑我的客户端程序如何能够创建 SSLSocket 并成功连接到服务器程序,即使密钥库文件(下面的 sessionKeyStore)为空。

以下代码将成功创建一个带有空密钥库的 TLSv1.2 套接字,并成功与我认为始终需要密钥交换的服务器程序握手。

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

tmf.init(sessionKeyStore); // sessionKeyStore IS NULL!!

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(sessionKeyStore, SSL_PASSWORD.toCharArray()); // password is not null
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
SecureRandom sc = createSecureRandom();
sc.setSeed(System.nanoTime());
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), sc);
SSLSocketFactory factory = sc.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket(server, serverPort);
((SSLSocket) socket).startHandshake();

我没有意识到客户端身份验证不包含在基本 TLS 握手中。仅对服务器进行身份验证。客户端身份验证是一次单独的握手,发生在服务器首次身份验证之后并且仅当服务器请求它时。问题是我需要专门告诉服务器套接字要求客户端证书验证包含在 TLS 握手中。在 Java JSSE 中执行此操作的方法是将以下代码添加到服务器端:

SSLContext sslContext = getSSLContext();
SSLServerSocketFactory sslserversocketfactory = sslContext.getServerSocketFactory();
SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port);
// Add the below to force a certificate request on the client.
sslserversocket.setNeedClientAuth(true);

https://www.comparitech.com/blog/information-security/tls-encryption