views:

2007

answers:

3

I'm trying to encrypt some content with an RSA private key.

I'm following this example: http://www.junkheap.net/content/public_key_encryption_java

but converting it to use private keys rather than public. Following that example, I think what I need to do is:

  • Read in a DER-format private key
  • Generate a PCKS8EncodedKeySpec
  • call generatePrivate() from KeyFactory to get a private key object
  • Use that private key object with the Cipher object to do the encryption

So, the steps:

The key was generated from openssl with:

openssl genrsa -aes256 -out private.pem 2048

and then was converted to DER format with:

openssl rsa -in private.pem -outform DER -out private.der

I generate the PKCS8EncodedKeySpec with:

     byte[] encodedKey = new byte[(int)inputKeyFile.length()];

 try {
  new FileInputStream(inputKeyFile).read(encodedKey);
 } catch (FileNotFoundException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }

 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey);
 return privateKeySpec;

And then generate the private key object with:

     PrivateKey pk = null;

 try {
  KeyFactory kf = KeyFactory.getInstance(RSA_METHOD);
  pk = kf.generatePrivate(privateKeySpec);
 } catch (NoSuchAlgorithmException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } catch (InvalidKeySpecException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 return pk;

However, on the call to:

  pk = kf.generatePrivate(privateKeySpec);

I get:

java.security.spec.InvalidKeySpecException: Unknown key spec.
at com.sun.net.ssl.internal.ssl.JS_KeyFactory.engineGeneratePrivate(DashoA12275)
at com.sun.net.ssl.internal.ssl.JSA_RSAKeyFactory.engineGeneratePrivate(DashoA12275)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:237)

Questions:

  • Is the general approach right?
  • Is the PCKS8EncodedKeySpec the right keyspec to use?
  • Any thoughts on the invalid key spec error?
+2  A: 

First of all, I'm confused why you are planning to use a Cipher to encrypt with a private key, rather than signing with a Signature. I'm not sure that all RSA Cipher providers will use the correct block type for setup, but it's worth a try.

Setting that aside, though, I think that you are trying to load a non-standard OpenSSL-format key. Converting it to DER with rsa is essentially just a base-64 decode; the structure of the key is not PKCS #8.

Instead, after genrsa, use the openssl pkcs8 command to convert the generated key to unencrypted PKCS #8, DER format:

openssl pkcs8 -topk8 -nocrypt -in private.pem -outform der -out private.der

This will produce an unencrypted private key that can be loaded with a PKCS8EncodedKeySpec.

erickson
Honestly, I was unaware of Signature.To make sure I understand its usage, I would initialize the signature object, call update with the bytes I want to sign, and then call sign? And then I can store the bytes returned from sign as my digital signature?
Wade Williams
Yes, that's the correct usage.
erickson
+1  A: 

You can't encrypt with public key. If JCE allows you to do that, it's just by accident.

You need to use signature. Here are the code snippet to do that,

signer = Signature.getInstance("SHA1withRSA");
signer.initSign(privateKey); // PKCS#8 is preferred
signer.update(dataToSign);
byte[] signature = signer.sign();
ZZ Coder
`s/public/private/` in your first line.
caf
Perfect - thanks much!
Wade Williams
+1  A: 

Its not an accident that encryption with private key is allowed. If you want to break a signature into individual hashing and encryption, then encrypting with private key is essential. Lets say I have a document which i need to sign and my key resides on a network HSM. Now either I stream the entire document to the HSM to sign or I can create a local hash and stream it to the HSM for encryption alone. My choice will depend on whether the local hash computation gives me better performance viz a viz delegated hash computation with network latency.

Kapil