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

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

socket = (SSLSocket) factory.createSocket(hostName, port); 

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

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

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

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

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

 socket.startHandshake(); System.out.println("Session ciphersuite is"+socket.getSession().getCipherSuite() ); 

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

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

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

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

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

SSLSocket JavaDoc中所述 :

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

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

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