如何指定要在SSL会话中使用的密码套件

use*_*868 12 java sockets ssl networking network-programming

我在端口443上创建了一个套接字,如下所示:

socket = (SSLSocket) factory.createSocket(hostName, port);
Run Code Online (Sandbox Code Playgroud)

然后,我想在这个插槽中看到启用的密码套件,我用过:

String[] enCiphersuite=socket.getEnabledCipherSuites();
System.out.println("Enabled ciphersuites are: "+Arrays.toString(enCiphersuite));
Run Code Online (Sandbox Code Playgroud)

然后,我想只选择一个我希望我的应用程序在与远程服务器创建握手时使用的密码套件.我做了以下事情:

String pickedCipher[] ={"TLS_RSA_WITH_AES_128_CBC_SHA"}; 
socket.setEnabledCipherSuites(pickedCipher);
System.out.println("ciphersuite set to: "+Arrays.toString(pickedCipher));
Run Code Online (Sandbox Code Playgroud)

然后我做了握手,并检查了会话密码套件:

socket.startHandshake();
System.out.println("Session ciphersuite is"+socket.getSession().getCipherSuite() );
Run Code Online (Sandbox Code Playgroud)

但我发现握手后打印输出语句中打印的密码名称(据我所知,这是会话中实际使用的密码)不是我之前设置的 setEnabledCipherSuites()

为什么我仍然没有看到我选择的密码套件是用过的密码套件?而且,我也试图getEnabledCipherSuites()在我之后打印出来setEnabledCipherSuites,发现列表没有改变到我设置的内容.我不确定何时打印启用的密码套件,这个密码套件列表是否依赖于Java并始终是相同的列表,还是取决于客户端或服务器上?有人可以解释一下吗?

编辑: 在握手之前我只有以下几行:

SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory(); 
SSLSocket socket=null;
try {
socket = (SSLSocket) factory.createSocket(hostName, port);
socket.setSoTimeout(15000); 
socket.startHandshake(); //handshake
.
.
Run Code Online (Sandbox Code Playgroud)

Bru*_*uno 6

我发现我在setEnableCipherSuite()之前添加了socket.getsession(),以便在设置之前打印出启用的cipheres.当我删除它时,密码已被设置.这是为什么 ?

SSLSocketJavaDoc中所述:

可以通过以下三种方式之一启动此连接上的初始握手:

  • 调用startHandshake明确地开始握手,或者
  • 任何在此套接字上读取或写入应用程序数据的尝试都会导致隐式握手,或者
  • 如果没有当前有效的会话,则调用getSession会尝试建立会话,并完成隐式握手.

如果在调用getSession()之前调用setEnabledCipherSuite(),则在尝试设置启用的密码套件时已完成握手,因此已选择此会话的密码套件.