为什么Java SSL连接仍然对相同的客户端和服务器套接字使用相同的密码



我听到一个朋友说:

对于Java中的每个SSL连接,当您查看SSL调试时,您可以看到握手过程中可用的密码列表,并且已选择该密码。

我听到另一个朋友说:

对于Java中的相同客户端和服务器SSL套接字,它们将始终选择相同的密码。

在我看来,这似乎不协调。你怎么能和一系列密码握手,每次都能想出同样的密码呢?

所以我写了一些代码来测试它——对于同一服务器和客户端的1000个连接,它似乎总是会选择相同的密码。为什么?

import javax.net.ssl.*;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
public class SSLServerClient {
private static Set<String> cipherNames = new HashSet();
public static void main(String[] args) throws IOException {
System.setProperty("javax.net.ssl.keyStore", "/path/KeyStore.jks");
System.setProperty("javax.net.ssl.trustStore", "/path/KeyStore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");

for (int i = 0; i < 1000; i++) {

SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverListeningSSLSocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket clientSocket = (SSLSocket) sslSocketFactory.createSocket(serverListeningSSLSocket.getInetAddress(),
serverListeningSSLSocket.getLocalPort());
SSLSocket serverCommsSSLSocket = (SSLSocket) serverListeningSSLSocket.accept();
final byte[] bytes = "--Hello World!".getBytes();
final OutputStream out = clientSocket.getOutputStream();

final DataInputStream in = new DataInputStream(serverCommsSSLSocket.getInputStream());
(new Thread() {
public void run() {
int len = 0;
try {
len = in.read();
final byte[] b = new byte[len];
in.readFully(b);
//System.out.println(new String(b));
} catch (SSLException | EOFException | SocketException | NegativeArraySizeException  e) {
// skip this one
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();

out.write(bytes.length);
out.write(bytes);
//System.out.println("protocol: "+ clientSocket.getSession().getProtocol());
//System.out.println("cipher: " + clientSocket.getSession().getCipherSuite());
cipherNames.add(clientSocket.getSession().getCipherSuite());
clientSocket.close();
serverCommsSSLSocket.close();
serverListeningSSLSocket.close();
}
System.out.println("Ciphers used: " + cipherNames);
}
}

输出为:

Ciphers used: [TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]

同一个密码1000次。

我的问题是:为什么Java SSL连接仍然对相同的客户端和服务器套接字使用相同的密码

握手根据某些完全确定的算法选择最佳可用密码。对于相同的输入(即双方声明可用的相同密码和版本,以及其他考虑因素(,它将选择相同的密码。

假设这个选择是客观上最好的,那么随机选择另一个(即劣质(密码是没有意义的。事实上,那是个坏主意。

在客户端中禁用TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(或提供更好的功能(,您将获得其他功能。

最新更新