我在Java keystore 中有两个证书/ key 对。这些键输入的别名为“foo”和“bar”。
我的TLS客户端(java程序)使用 keystore 。 TLS客户端身份验证在连接打开期间完成。
TLS服务器从客户端请求证书时,客户端程序应使用“foo”键输入。
现在,客户端在连接握手期间向服务器发送了错误的证书(“条”)。
如何在连接之前告诉SSLSocket想要的 key 输入别名?
当前代码如下:
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();