OpenJDK 11.0.2 2019-01-15
在使用TLSv1.2和密码套件TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384连接到使用TLSv1.2的Jetty(9.4.14.v20151114)服务器时,我正在使用相互身份验证。
我的客户端使用标准的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 $ Service,该服务支持所选的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实现的。
有什么办法可以解决此问题?我可以让客户端以某种方式选择与PKCS11 KeyStore一起使用的客户端签名算法(例如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>