如何在连接之前告诉SSLSocket所需的密钥条目的别名?

我在java密钥库中有两个证书/密钥对。 这些关键词的别名是“foo”和“bar”。

我的TLS客户端(java程序)使用密钥库。 在连接打开期间完成TLS客户端身份validation。 当TLS服务器从客户端请求证书时,客户端程序应使用“foo”键入。 现在,客户端在连接握手期间向服务器发送错误的证书(“bar”)。

如何在连接之前告诉SSLSocket所需的密钥条目的别名?

目前代码如下:

final SSLSocket ss = (SSLSocket)SSLSocketFactory.getDefault().createSocket(); ss.setEnabledProtocols( new String[] {"TLSv1"}); ss.connect( targetAddress ); 

默认的KeyManager将发送它找到的第一个证书,该证书与服务器请求的条件相匹配,也就是说,它将发送它找到的第一个证书,它可以构建一个证书链,其中包含服务器发送的一个CA名称。请求。

如果您总是希望选择特定的别名,则需要实现自己的X509KeyManager ,可能包含默认管理器。 沿着这些线路的东西应该工作(没有测试这个实际的代码,可能会有一些拼写错误):

 KeyStore keystore = ... // create and load your keystore. KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keystore, password.toCharArray()); final X509KeyManager origKm = (X509KeyManager)kmf.getKeyManagers()[0]; X509KeyManager km = new X509KeyManager() { public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return "foo"; } public X509Certificate[] getCertificateChain(String alias) { return origKm.getCertificateChain(alias); } // Delegate the rest of the methods from origKm too... } 

然后将它用于您的SSLContext

 SSLContext sslContext = sslContext.getInstance("TLS"); sslContext.init(new KeyManager[] { km }, null, null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();