1

I'm trying to send a Client certificate to the server. I'm constructing a SSLSocketFactory on a HttpURLConnection.

I think I need to make the key available via a KeyManager that the SSLSocketFactory knows about. The trouble I'm having is getting the key into the KeyManager.

The private key and certificate are in a PEM file (and they can't be in a keystore file). I know how to read/decode the file and I've successfully validated the client certificate. But when I try to put the key (as byte[]) into the KeyManager, it complains: 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});

What's the right way to do this?

2
  • Just so that I better understand the root of your problem, what context are you doing this in ? There are a number of libraries and frameworks out there that can handle this sort of thing for you automatically. One such library is the JSch (J Secure Channel) library. Commented Nov 12, 2010 at 0:11
  • This is code for clients who don't want to use any additional libraries (which would have to be vetted). The client is calling a web service that requires a client cert for authorization. And the deployment uses .PEM files. Commented Nov 12, 2010 at 3:01

2 Answers 2

2

The trick to making this work was to convert the PEM file to a different format. I did it externally for now with 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

Then, I was successfully able to add the key and certificate to the in-memory keystore:

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});
Sign up to request clarification or add additional context in comments.

Comments

1

I got the same exception for reading the private key from an RSA encrypted file. I fixed the issue by instead of creating the entry in the KeyStore in it's binary format:

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

I simply create it as a Key Object instead:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.