Java Keystore - programatically select the certificate to use from keystore file

隐身守侯 提交于 2021-02-06 09:32:06

问题


I have a java keystore file which contains multiple client certificates. I wish to select just one of these certificates in my Java application to connect to a service. Is there a simple way to do this? The only way I've found a solution to this so far is to create a new KeyStore in the program using the client cert details (found by its alias) from the original keystore file. I though there might be a simple way to just say "use the cert from the keystore.jks file with this alias", rather than have to create a new keystore just for the cert you want to use. Code is as follows:

        // 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);

回答1:


Your question is similar to How I can tell alias of the wanted key-entry to SSLSocket before connecting?

The default KeyManager will select the first certificate in handshake (according to CA list sent by server), You can build your own X509KeyManager to specify the alias to be used wrapping the default.

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 ...
}

Set the new keyManager in SSLContext

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


来源:https://stackoverflow.com/questions/42442721/java-keystore-programatically-select-the-certificate-to-use-from-keystore-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!