我正在尝试将客户端证书发送到服务器。我正在HttpURLConnection上构建一个SSLSocketFactory。
我想我需要通过SSLSocketFactory知道的KeyManager提供密钥。我遇到的麻烦就是将密钥输入KeyManager。
私钥和证书位于PEM文件中(并且它们不能位于密钥库文件中)。我知道如何读取/解码文件,我已经成功验证了客户端证书。但是当我尝试将密钥(作为byte [])放入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 :(得分: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 :(得分:1)
我从RSA加密文件中读取私钥时遇到了同样的异常。我修复了这个问题,而不是在它的二进制格式中创建KeyStore中的条目:
keyStore.setKeyEntry(IdentityManagement.ALIAS, privateKey.getEncoded(), new X509Certificate[]{(X509Certificate)cert});
我只是将其创建为关键对象:
keyStore.setKeyEntry(IdentityManagement.ALIAS, privateKey, password.toCharArray(), new X509Certificate[]{(X509Certificate)cert});