2

When converting a password-protected PEM/PKCS1-encoded private key to DER format one is not able to encrypt the key, OpenSSL automagically asks for the password and writes the plain-text key in the output file.

However, I understand that PKCS8-encoding does support encryption when converted to DER format, my problem is that I can't make OpenSSL write an encrypted file. I have tried:

openssl pkey -inform PEM -in key_pkcs8_encrypted.pem -outform DER -out key_pkcs8_encrypted.der

...but OpenSSL asks for the password and writes a decrypted file (verified by diffing it with the DER version of the decrypted PEM key).

I have also tried:

openssl rsa -des3 -in key_pkcs8_unencrypted.pem -outform DER -out key_pkcs8_encrypted.der

...in the hope that OpenSSL would ask for a password and encrypt the output file, as it does in the -outform PEM case but it does not, it just writes an unencrypted file.

And finally I have tried:

openssl rsa -des3 -in key_pkcs8_unencrypted.pem -passout pass:mypassword -outform DER -out key_pkcs8_encrypted.der

...but that also writes an unencrypted file.

Am I correct that PEM/PKCS8 when converted to DER does support encryption and, if so, does anyone know how I might persuade OpenSSL to do it for me?

Edit: I am aware of this post but it doesn't address the part about how OpenSSL can be asked to generate a password-protected DER file.

Rob
  • 131
  • 4
  • Ah, I've just tried `openssl pkcs8 -topk8 -inform pem -in key_pkcs1_encrypted.pem -outform DER -out key_pkcs8_encrypted.der` and that asked for both decryption and encryption passwords, plus the DER file is now different, so I guess that's done it? – Rob Feb 11 '21 at 15:24
  • Feel free to answer your own question below. –  Feb 11 '21 at 15:43
  • Hmmm, no, if I then run `openssl pkey -inform DER -passin pass:mypassword -in key_pkcs8_encrypted.der -text` OpenSSL acts like it's been given garbage as its input. Hmph. – Rob Feb 11 '21 at 16:33
  • Seems as though the OpenSSL `pkey` command is ONLY for PKCS1 format keys, while the `pkcs8` command doesn't have a `-text` option. So if I use `openssl pkcs8 -inform DER -in key_pkcs8_encrypted.der` OpenSSL prompts for a password and sends a PEM-coded file to `stdout` which _appears_ to contain valid ASN.1. Maybe it is OK. – Rob Feb 11 '21 at 16:46
  • 1
    Does this answer your question? [Is it possible to protect a DER private key with a password?](https://security.stackexchange.com/questions/103329/is-it-possible-to-protect-a-der-private-key-with-a-password) – gowenfawr Feb 11 '21 at 17:12
  • Partially: that's where I got the hint that DER with PKCS1 didn't support encryption but DER with PKCS8 did. But it doesn't say how to persuade OpenSSL to encrypt a PKCS8-encoded key in DER format, hence the question here. It's possible that I've found the right runes now but the thing I'm trying to test by generating this encrypted private key still doesn't like it. Now I need to find out whether I am at fault or it is :-). – Rob Feb 11 '21 at 17:20
  • PEM is just the base64 encoded DER data - so just use openssl base64 to convert from DER to PEM and add an ascii header and footer – matthias_buehlmann Feb 11 '21 at 22:51
  • Yes, could do, though the things I'm using the output to test (embedded communications devices) might be sensitive about exactly what's in the header so, if at all possible, I'd rather use a tool that behaves in a "reference" manner. – Rob Feb 12 '21 at 00:58
  • 1
    **It's inconsistent.** `pkey [-outform pem]` writes PKCS8 PEM and can be encrypted, but `pkey -outform der` writes _traditional_ DER for most algorithms (PKCS1 for RSA, SEC1 for ECC, adhoc for DSA) which cannot, but since OpenSSL had no traditional key format for DH it writes that as PKCS8 (but still doesn't encrypt!). `pkcs8 -topk8 -outform der` is indeed the only way at commandline to create PKCS8-encrypted DER. (`rsa` and also `genrsa` writes traditional PEM or traditional=PKCS1 DER, never any PKCS8.) ... – dave_thompson_085 Feb 12 '21 at 05:28
  • 1
    ... `pkey -inform der` uses an awful kludge called `d2i_AutoPrivateKey` and can actually read _all_ traditional formats _and_ PKCS8-clear but not PKCS8-encrypted, as you tried. Bleah. Do you have any doc, or examples, of what these devices want? – dave_thompson_085 Feb 12 '21 at 05:36
  • @dave_thompson_085: many thanks for confirming this, does seem quite kludgy, many thanks for confirming. The reason I'm doing this is because [our - I'm working with my company's devices] documentation is lacking in this area and I'd like to do my own checking before I go hassle the people who should address it. You have given me the confidence to do that :-). – Rob Feb 12 '21 at 10:30
  • @Rob. The header is well defined. It‘s just five dashed followed by BEGIN followed by a label followed by five dashes. Same for footer. label will be the same as for the unencrypted one – matthias_buehlmann Feb 12 '21 at 17:10
  • True, but I've just found out that one of the things I'm testing rejects "BEGIN PRIVATE KEY" but accepts "BEGIN RSA PRIVATE KEY", hence I have to be very careful. – Rob Feb 12 '21 at 17:27
  • Note that quite often you need these private keys together with a certificate chain. In that case PKCS#12 is the way to go, not PKCS#8 (although, usually, within PKCS#12 sits a PKCS8ShroudedKeyBag, so then encrypted PKCS#8 is used *internally*. – Maarten Bodewes Mar 14 '21 at 14:19

1 Answers1

1

As @dave_thompson_085 above points out, there is only one way to do this with OpenSSL which is:

openssl pkcs8 -topk8 -in key_pkcs1_encrypted.pem -outform DER -out key_pkcs8_encrypted.der

As he says, beware that OpenSSL gets a bit "kludgy" where support for encrypted PKCS8 is concerned (specifically pkey cannot read PKCS8-encrypted format input files).

Rob
  • 131
  • 4