简体   繁体   English

在SSL握手期间,Java客户端如何使用本机Windows-MY存储来提供其客户端证书?

[英]How can a Java client use the native Windows-MY store to provide its client certificate as required during a SSL handshake?

This question was also posted at TLS client authentication fails when using SunMSCAPI but has not found an answer. 此问题也发布在TLS客户端身份验证失败时使用SunMSCAPI但未找到答案。

I have a Java6 application running on a Windows Win2008R2 client that connects to a server requiring client certificates. 我有一个在Windows Win2008R2客户端上运行的Java6应用程序,它连接到需要客户端证书的服务器。 The Java application is required to use the native Windows stores, ie Windows-Root and Windows-My, and employs the SunMSCAPI provider. Java应用程序需要使用本机Windows存储,即Windows-Root和Windows-My,并使用SunMSCAPI提供程序。 The Windows certificate management console reports that both the client cert and CA cert that signed it are correct and enabled for all purposes. Windows证书管理控制台报告客户端证书和签署它的CA证书都是正确的,并且可以用于所有目的。

Server verification works exactly as expected, but client authentication fails when the client throws a SSLException complaining that the privatekey is not an RSA private key. 服务器验证与预期完全一致,但是当客户端抛出SSLException抱怨私钥不是RSA私钥时,客户端身份验证失败。 However, when the Java default provider is used instead, and the same client certificate is taken from a JKS keystore, ie SunMSCAPI and the Windows stores are not used, client authentication works just as expected and the SSL connection succeeds. 但是,当使用Java默认提供程序,并且从JKS密钥库获取相同的客户端证书时,即不使用SunMSCAPI和Windows存储时,客户端身份验证将按预期工作,并且SSL连接成功。

When executed, the application reports that it's using the SunMSCAPI provider and is able to print the correct client certificate as well as information about its RSAPrivateKey. 执行时,应用程序报告它正在使用SunMSCAPI提供程序,并且能够打印正确的客户端证书以及有关其RSAPrivateKey的信息。 Tracing indicates that the client exception occurs after the servers 'Hello Done' as its response to the server's certificate request is being prepared. 跟踪表示客户端异常发生在服务器“Hello Done”之后,因为它正在准备对服务器的证书请求的响应。

The relevant code bits for the client keystore portion of this are: 客户端密钥库部分的相关代码位是:

SSLContext sslContext = SSLContext.getInstance("TLS");
KeyManagerFactory kFac = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
Provider pvdr = new sun.security.mscapi.SunMSCAPI();  
Security.insertProviderAt(pvdr,1);
KeyStore kStore = KeyStore.getInstance("Windows-MY",pvdr);
kStore.load(null,null);
kFac.init(kstore,null);
sslContext.init(kFac.getKeyManagers(), <a trust factory>.getTrustManagers(), new java.security.SecureRandom());
SSLSocketFactory sockFactory = SSLSocketFactory(sslContext);
SSLSocket sslSock = (SSLSocket)sockFactory.createSocket(<some destination host>, <some destination port>);
BufferedInputStream bInStr = new BufferedInputStream(sslSock.getInputStream());
bInStr.read(<the read arguments>);   <<< exception thrown in here

Any pointers or suggestions will be greatly appreciated! 任何指针或建议将不胜感激!

The stacktrace shown in your link shows the problem to be at RSA's JSSL provider. 链接中显示的堆栈跟踪显示了RSA的JSSL提供程序存在的问题。 Especially for this case you should use Sun/Oracle's JSSE provider. 特别是对于这种情况,您应该使用Sun / Oracle的JSSE提供程序。 It's the default one anyway. 无论如何,这是默认的。

Call it as 称之为

SSLContext sslContext = SSLContext.getInstance("TLS", "SunJSSE");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM