2010-11-11 269 views
1

我试图发送一个客户端证书到服务器。我正在HttpURLConnection上构造一个SSLSocketFactory。java HttpsURLConnection和发送客户端证书

我想我需要通过KeyManager提供SSLSocketFactory知道的密钥。我遇到的麻烦是将Key输入到KeyManager中。

私钥和证书位于PEM文件中(并且它们不能位于密钥库文件中)。我知道如何读取/解码文件,并且我已经成功验证了客户端证书。但是,当我试图把重点(以字节[])进入的KeyManager,它抱怨:java.security.KeyStoreException: key is not encoded as EncryptedPrivateKeyInfo

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
KeyStore ks = KeyStore.getInstance("JKS"); 
ks.load(null); // init the keystore 

// This Fails: it wants it encoded as EncryptedPrivateKeyInfo 
ks.setKeyEntry("MyAlias", clientKeyAsBytes, new Certificate[]{clientCert}); 

什么是做到这一点的正确方法?

+0

只是让我更好地理解根你的问题,你在做什么背景?有许多库和框架可以自动处理这类事情。一个这样的库是JSch(J Secure Channel)库。 – 2010-11-12 00:11:58

+0

这是客户不想使用任何额外的库(这将不得不审查)的代码。客户正在调用一个需要授权客户端证书的Web服务。部署使用.PEM文件。 – 2010-11-12 03:01:05

回答

2

使这项工作的诀窍是将PEM文件转换为不同的格式。我这样做是外部现在使用OpenSSL

openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out client-key.der -outform DER 
openssl x509 -in cert.pem -inform PEM -out client-cert.der -outform DER 

然后,我是能够成功地将密钥和证书添加到内存中的密钥库:

PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(clientKeyAsBytes); 
PrivateKey ff = kf.generatePrivate(keysp); 

// This works with DER format of key bytes 
ks.setKeyEntry("MyAlias", clientKeyAsBytes, new Certificate[]{clientCert}); 
1

我得到了同样的异常用于读取私人密钥来自RSA加密文件。我用的,而不是建立在它的密钥库中的项解决了该问题的二进制格式:

keyStore.setKeyEntry(IdentityManagement.ALIAS, privateKey.getEncoded(), new X509Certificate[]{(X509Certificate)cert}); 

我简单地创建为重点对象,而不是:

keyStore.setKeyEntry(IdentityManagement.ALIAS, privateKey, password.toCharArray(), new X509Certificate[]{(X509Certificate)cert});