19

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

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

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

目前代码如下:

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

1 回答 1

28

默认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();
于 2013-03-04T13:25:27.790 回答