0

I have got a passphrase protected PEM key file generated by OpenSSL

openssl genrsa -aes128 -passout stdin -out testfile.pem

I have also generated a public key file using OpenSSL

openssl rsa -in testfile.pem -out testfile_pub.pub ( propts for password)

I would like to be able to use this private key to sign my claims etc. and then send requests. What I am struggling to understand (or more like confirming my understanding about) are the following:

1) My private key is password protected, does it mean no one can actually generate the public key without unlocking it first? i.e. that's where the protection is?

2) If I was to read this encrypted private key PEM file in Java, I would have to do something similar to:

\\ 1. Read file as string \\ 2. Replace all boring bits e.g. begin/end/rsa/private/public/key/enc/-- \\ 3. decode using Base64 \\ 4. read as PKCS8 keyspec and generate PrivateKey object

but doesn't this mean that no one is actually stopping me from reading the keyspecs ? I guess what I am trying to compare with is how we generate JKS keys with optional keypass/storepass. But may be I am not supposed to compare this.

Could anyone help me understand?

Thanks,

ha9u63a7
  • 6,233
  • 16
  • 73
  • 108
  • If you want to stay with 'traditional' (PKCS1) format used by `genrsa` and `rsa` and can use BouncyCastle, see https://stackoverflow.com/questions/44681737/ – dave_thompson_085 Jun 02 '19 at 03:28

1 Answers1

2

openssl rsa -in testfile.pem -out testfile_pub.pub does not export the public key, it actually exports the private key out in clear text (if you provided the correct password). To export the public key use the -pubout option.

Yes you will need the password to export the public key.

To import the private key in Java you will need to convert it to PKCS8 first:

openssl pkcs8 -topk8 -in testfile.pem -inform pem -out testfile_pkcs8.pem -outform pem

Then you can import it in Java like:

String encrypted = new String(Files.readAllBytes(Paths.get("testfile_pkcs8.pem")));  
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");  
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");  
EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.decode(encrypted));  
PBEKeySpec keySpec = new PBEKeySpec("mypassword".toCharArray()); // password  
SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName());  
PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));  
KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
PrivateKey encryptedPrivateKey = keyFactory.generatePrivate(encodedKeySpec);  

No, it doesn't mean that anyone can read the key, because you still have to provide the password.

mnistic
  • 10,866
  • 2
  • 19
  • 33
  • Or `openssl pkcs8 -topk8 -nocrypt -outform der` does the decrypt and de-PEM for you, then read directly into `PKCS8EncodedKeySpec` -- but if any malefactor can get access to that file your security is ruined. (If you pass it as piped stdin or other transient pipe, that helps.) – dave_thompson_085 Jun 02 '19 at 03:15
  • 2
    @mnistic I tried this code and it's throwing exception when I try to construct `EncryptedPrivateKeyInfo` from the decoded bytes. `java.io.IOException: ObjectIdentifier() -- data isn't an object ID (tag = 48)` – ha9u63a7 Jun 02 '19 at 12:24
  • 1
    How did you create your PKCS8 file? Did you use the exact command line in my answer? Is the first line in the file "-----BEGIN ENCRYPTED PRIVATE KEY-----"? – mnistic Jun 02 '19 at 13:15
  • @mnistic yes I did exactly as above. I went ahead and used BouncyCastle to read the input. It seems Java cannot reliably read encrypted Private Key files and there was a JDK bug for a while until JDK 11 was released. – ha9u63a7 Jun 12 '19 at 05:17
  • my pem file contains Bag attributes like friendly name etc. how to remove all those? – sakura Mar 31 '21 at 13:20