Dave C
Dave C

Reputation: 1652

java HttpsURLConnection and sending Client Certificates

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?

Upvotes: 1

Views: 4108

Answers (2)

Christo Smal
Christo Smal

Reputation: 615

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});

Upvotes: 1

Dave C
Dave C

Reputation: 1652

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});

Upvotes: 2

Related Questions