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

时间:2012-08-06 16:59:58

标签: java authentication ssl

此问题也发布在TLS client authentication fails when using SunMSCAPI,但未找到答案。

我在Windows Win2008R2客户端上运行Java6应用程序,该客户端连接到需要客户端证书的服务器。 Java应用程序需要使用本机Windows存储,即Windows-Root和Windows-My,并使用SunMSCAPI提供程序。 Windows证书管理控制台报告客户端证书和签署它的CA证书都是正确的,并且可以用于所有目的。

服务器验证与预期完全一致,但是当客户端抛出SSLException抱怨私钥不是RSA私钥时,客户端身份验证失败。但是,当使用Java默认提供程序,并且从JKS密钥库获取相同的客户端证书时,即不使用SunMSCAPI和Windows存储时,客户端身份验证的工作方式与预期一致,并且SSL连接成功。

执行时,应用程序报告它正在使用SunMSCAPI提供程序,并且能够打印正确的客户端证书以及有关其RSAPrivateKey的信息。跟踪表示客户端异常发生在服务器“Hello Done”之后,因为它正在准备对服务器证书请求的响应。

客户端密钥库部分的相关代码位是:

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

任何指针或建议都将不胜感激!

1 个答案:

答案 0 :(得分:2)

链接中显示的堆栈跟踪显示了RSA的JSSL提供程序存在的问题。特别是对于这种情况,您应该使用Sun / Oracle的JSSE提供程序。无论如何,这是默认的。

将其命名为

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