Я слышал, как один друг сказал:
Для каждого SSL-соединения в Java - когда вы смотрите на отладку SSL - вы можете увидеть список шифров, доступных во время процесса рукопожатия, и этотвыбран.
Я слышал, как другой друг сказал:
Для одного и того же сокета SSL клиента и сервера в Java - они всегда будут выбирать один и тот же шифр.
Это мне казалось несоответствующим.Как вы могли бы рукопожатие со списком шифров и при этом каждый раз придумывать один и тот же шифр?
Поэтому я написал некоторый код для его проверки - и казалось, что для 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 раз.
Мой вопрос: Почему в SSL-соединении Java все еще используется один и тот же шифр для одинаковых сокетов клиента и сервера?