java SSLSocketFactory如何在SSL中从密钥库中选择服务器证书和私钥

时间:2018-06-05 12:56:39

标签: java ssl keystore embedded-jetty ports

我有一个Jetty服务器,我打开多个SSL端口并设置SslContextFactory我将其指向我的自定义密钥库,我在其中拥有所有SSL端口的证书。

public static SslContextFactory getCustomSSLContextFactory() throws IOException {
    KeyStoreInfo keyStoreInfo = KeyStoreInfo.getInstance();
    SslContextFactory sslContextFactory = new SslContextFactory(mycustomkeystorepath);
    sslContextFactory.setKeyStorePassword(mykeystorepassword);
    sslContextFactory.setKeyStoreType(keystoretype);
    sslContextFactory.setTrustStorePath(defaultcatruststore);
    sslContextFactory.setTrustStorePassword(password);
    sslContextFactory.setTrustStoreType(truststoretype);
    sslContextFactory.setNeedClientAuth(true);
    return sslContextFactory;       
}

SslContextFactory我在ServerConnector SslConnectionFactory中进行了设置。我有多个ServerConnector,并且都具有相同的SslContextFactory

我的问题是我在自定义密钥库中有多个PKI-cert和私钥。 SslConnectionFactory如何知道哪个PKI-cert和私钥属于哪个SSL端口?

2 个答案:

答案 0 :(得分:1)

SSL证书与服务器的某些域/主机名+端口相关。因此,域/主机名+端口数据存在于证书中。当您建立连接时,SslConnectionFactory将查看特定域/主机名+端口是否存在证书,如果存在,它将使用该证书以及与之相关的私钥进行握手。

请记住,默认情况下,域名的SSL证书知道端口是443.同样,它适用于不同的端口。

答案 1 :(得分:1)

用于SSLContext服务器的证书和密钥由初始化的KeyManager选择。

如果您想手动选择证书和/或密钥,您可以实现自己的KeyManager并将代码放入:

String chooseServerAlias(String keyType, Principal[] issuers, Socket socket)

PrivateKey getPrivateKey(String alias)

第一种方法允许您指定哪个别名标识证书,第二种方法获取第一种方法中定义的别名并加载私钥。

如果以一种方式实现第一种方法,它返回密钥库中密钥/证书的别名,则可以将第二种方法委托给现有的KeyManager实例。

结果代码如下所示:

String algorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
keyManagerFactory.init(keyStore, "".toCharArray());

KeyManager[] defaultKeyManagers = keyManagerFactory.getKeyManagers();
KeyManager mykm = new MyKeyManager((X509KeyManager) defaultKeyManagers[0]);

sslContext.init(new KeyManager[] { mykm } , trustManagerFactory.getTrustManagers(), new SecureRandom());

static class  MyKeyManager implements X509KeyManager {
    final X509KeyManager delegate;

    public KeyManager(X509KeyManager delegate) {
        this.delegate = delegate;
    }

    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
        delegate.chooseClientAlias(keyType, issuers, socket);
    }

    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
        ... implement your code here
    }

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

    public String[] getServerAliases(String keyType, Principal[] issuers) {
        return delegate.getServerAliases(keyType, issuers);
    }

    public String[] getClientAliases(String keyType, Principal[] issuers) {
        return delegate.getClientAliases(keyType, issuers);
    }

    public PrivateKey getPrivateKey(String alias) {
        return delegate.getPrivateKey(alias);
    }
}