2013-03-04 58 views
8

我在一个java密钥库中有两个证书/密钥对。这些关键词的别名是“foo”和“bar”。如何在连接之前将所需密钥条目的别名告诉SSLSocket?

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

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

目前,代码如下:

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

什么是对的“酒吧”项目?为什么你有两个客户端证书? – EJP 2013-03-04 23:10:30

+0

@EJP:客户端程序是一个测试程序。测试不同类型的用例需要几个关键条目。 – SKi 2013-03-05 07:55:07

回答

13

默认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(); 
+0

这看起来很有希望。我今天会尝试这个。 – SKi 2013-03-05 07:59:24

+0

@ User1:你可以发布完整的代码来实现这个吗? – rkkreddy 2016-10-14 15:14:33

相关问题