Java密钥库 - 以编程方式从密钥库文件中选择要使用的证书

问题描述:

我有一个包含多个客户端证书的java密钥库文件。我希望在我的Java应用程序中仅选择其中一个证书来连接到服务。有没有简单的方法来做到这一点?到目前为止,我找到解决方案的唯一方法是使用原始密钥库文件中的客户端证书详细信息(通过其别名找到)在程序中创建一个新的KeyStore。我虽然可能只是简单地说“使用带有这个别名的keystore.jks文件中的证书”,而不是仅仅为你想使用的证书创建一个新的密钥库。代码如下:Java密钥库 - 以编程方式从密钥库文件中选择要使用的证书

 // Set up Client Cert settings 
     KeyStore clientCertStore = KeyStore.getInstance("JKS"); 
     clientCertStore.load(new FileInputStream(clientKeystoreLocation), clientKeystorePassword);    

     // Create temporary one keystore, then extract the client cert using it's alias from keystore.jks, then create 
     // a new keystore with this cert, that the process will use to connect with. 
     KeyStore tempKstore = KeyStore.getInstance("JKS"); 
     tempKstore.load(null); 
     tempKstore.setKeyEntry(certificateAlias, clientCertStore.getKey(certificateAlias, bwConfig.clientKeystorePassword), 
       clientKeystorePassword, clientCertStore.getCertificateChain(certificateAlias)); 
     clientCertStore = tempKstore; 

     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     keyManagerFactory.init(clientCertStore, clientKeystorePassword);    

     // Set up Truststore settings 
     File truststoreFile = new File(TrustStoreLocation); 
     KeyStore trustStore = KeyStore.getInstance("JKS"); 
     trustStore.load(new FileInputStream(truststoreFile), TrustStorePassword); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     trustManagerFactory.init(trustStore); 

     // Set to TLS 1.2 encryption 
     SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); 
     sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 

     SSLSocketFactory ssf = sslContext.getSocketFactory(); 
     ssf.createSocket(serviceURL.getHost(), servicePort); 

     bp.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", ssf); 

你的问题是类似How I can tell alias of the wanted key-entry to SSLSocket before connecting?

默认KeyManager将选择在握手的第一个证书(根据服务器发送的CA列表中),你可以建立自己的X509KeyManager指定要使用的别名包装默认值。

final X509KeyManager origKm = (X509KeyManager)keyManagerFactory.getKeyManagers()[0]; 
X509KeyManager km = new X509KeyManager() { 
    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { 
     return "alias"; 
    } 

    public X509Certificate[] getCertificateChain(String alias) { 
     return origKm.getCertificateChain(alias); 
    } 

// override the rest of the methods delegating to origKm ... 
} 

坐落在SSLContext

sslContext.init(new KeyManager[] { km }, trustManagerFactory.getTrustManagers(), null); 
keyManager