Java / Jetty: как выбрать алгоритм подписи в аутентификации клиента TLS - PullRequest
1 голос
/ 08 мая 2019

Преамбула

OpenJDK 11.0.2 2019-01-15

Я использую взаимную аутентификацию при подключении к серверу Jetty (9.4.14.v20151114) с использованием TLSv1.2, снабор шифров TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.

Мой клиент использует стандартные механизмы Java TLS:

javax.net.ssl.SSLContext sslContext = SSLContext.getInstance("TLS");
javax.net.ssl.KeyManager keyManager = ...;
javax.net.ssl.TrustManager trustManager = ...;
sslContext.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, null);
javax.net.ssl.SSLSocketFactory socketFactory = sslContext.getSocketFactory();
// ... and so on

Мой клиент использует хранилище ключей PKCS11, поддерживаемое смарт-картой:

Provider pkcs11Provider = Security.getProvider("SunPKCS11").configure(configFile);
Security.addProvider(pkcs11Provider);
CallbackHandlerProtection callbackHandler = ...;
KeyStore keyStore = KeyStore.Builder.newInstance("PKCS11", provider, callbackHandler).getKeyStore();

Проблема

Jetty отправляет довольно длинный список поддерживаемых алгоритмов подписи для использования при аутентификации клиента.Клиент решает, какой из них использовать, вызывая:

sun.security.ssl.SignatureScheme.getPreferableAlgorithm(List<SignatureScheme> schemes, PrivateKey signingKey, ProtocolVersion version);

Это выбирает схему подписи RSASSA-PSS.

Позже, в методе

java.security.Signature$Delegate.chooseProvider(int type, java.security.Key key, SecureRandom sr)

клиент выбирает службу java.security.Provider $, которая поддерживает выбранный алгоритм RSASSA-PSS.Этот провайдер для службы RSASSA-PSS является sun.security.rsa.SunRsaSign.Поставщик SunPKCS11, используемый в хранилище ключей, не предоставляет службу RSASSA-PSS.

Проблема заключается в том, что служба этого провайдера SunRsaSign не поддерживает закрытый ключ на основе PKCS11, используемый для подписи, и я получаю следующую трассировку стека(скопировано вручную, остерегайтесь опечаток):

java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11PrivateKey
    at java.base/java.security.Signature$Delegate.chooseProvider(Signature.java:1163)
    ...

Вопрос

Кажется, что выбранный алгоритм подписи реализован java.security.Provider, который не поддерживает PrivateKey, используемый ваутентификация клиента.

Есть ли способ обойти это?Можно ли заставить клиента каким-либо образом выбрать алгоритм подписи клиента, который работает с хранилищем ключей PKCS11 (например, RSA_PKCS1_SHA512)?Могу ли я настроить сервер Jetty таким образом, чтобы он не предлагал алгоритмы подписи клиента, которые не работают?

Редактировать

Конфигурация Jetty SSLContextFactory (может содержать опечатки):

<New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
    <Set name="keyStorePath">keystore.jks</Set>
    <Set name="keyStorePassword">...</Set>
    <Set name="trustStorePath">truststore.jks</Set>
    <Set name="needClientAuth">true</Set>
    <Set name="includeProtocols">
        <Array type="java.lang.String">
            <Item>TLSv1.2</Item>
        </Array>
    </Set>
    <Set name="includeCipherSuites">
        <Array type="java.lang.String">
            <Item>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</Item>
        </Array>
    </Set>
</New>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...