一直在尝试使用 PKCS#11 令牌(智能卡)作为客户端上的 KeyStore(而不是 TrustStore)来对 TLS 连接进行客户端身份验证。但是,SSL 握手失败并显示SSLException
以下消息:
出乎意料的是,privatekey 不是 RSA 私钥。
这不可能是真的,因为智能卡上的私钥/证书对是 RSA 密钥。我是否缺少一些将智能卡用作 JSSE 的 KeyStore 的配置?
这是我的配置详细信息:
首先,将 Sun PKCS#11 Provider 配置为使用与智能卡接口的“ActivCard”dll。Sun PKCS#11 Provider 配置文件只包含“name”和“library”属性。
SunPKCS#11 提供程序的实例化如下所示:
java.security.AuthProvider provider =
new sun.security.pkcs11.SunPKCS11.SunPKCS11(<Configuration file>);
然后,java.security.KeyStore
使用以下代码从智能卡中实例化对象:
KeyStore.ProtectionParameter thePasswordProtection =
new KeyStore.PasswordProtection( null );
KeyStore.Builder theBuilder =
KeyStore.Builder.newInstance( "PKCS11", provider, thePasswordProtection );
java.security.KeyStore theKeyStore = theBuilder.getKeyStore();
此外,这个实例化KeyStore
用于让KeyManagerFactory
JSSE 使用下面的代码:
KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.
getInstance( "SunX509", "SunJSSE" );
kmf.init( theKeyStore, <smart card pin> );
此 KeyManagerFactory 用于然后初始化 SSLContext,然后用于实例化 SSLSocket。
根据Oracle 的 JSSERefGuide for Java 6中的说明,这就是我需要做的全部工作。虽然在以编程方式使用密钥库时不需要设置以下系统属性,但我也尝试添加系统属性:
javax.net.ssl.keyStoreType
到PKCS11
,javax.net.ssl.keyStore
到NONE
和javax.net.ssl.keyStoreProvider
配置文件中为 Sun PKCS#11 提供程序指定的名称。
有什么想法我在这里做错了吗?任何指示或想法将不胜感激。