Как java SSLSocketFactory выбирает сертификат сервера и закрытый ключ во время SSL из хранилища ключей - PullRequest
0 голосов
/ 05 июня 2018

У меня есть сервер 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.И у меня есть несколько ServerConnectors, и все они имеют одинаковые SslContextFactory.

Мой вопрос заключается в том, как у меня есть несколько PKI-сертификат и закрытый ключ в хранилище пользовательских ключей.Как SslConnectionFactory узнает, какой PKI-сертификат и закрытый ключ принадлежат какому порту SSL?

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Сертификат и ключ, используемые для сервера 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);
    }
}
0 голосов
/ 05 июня 2018

Сертификат SSL относится к какому-либо домену / имени хоста + порту сервера.Таким образом, данные о домене / имени хоста + порту присутствуют в сертификате.Когда вы устанавливаете соединение, SslConnectionFactory проверяет, присутствует ли сертификат для конкретного домена / имени хоста + порта, и если он присутствует, он будет использовать этот сертификат и закрытый ключ, относящийся к нему, для выполнения рукопожатия.

Помните, что по умолчанию SSL-сертификаты для доменного имени знают, что порт 443. Аналогично, он будет работать для разных портов.

...