This answer states that encrypting a private key using openssl rsa -aes256 isn't secure, because the md5 hash of the password is used as encryption key.

But what if I do openssl pkcs12 -export -in client.crt -inkey client.key -name client -out client.p12 -password pass:12345 instead? (Using a better password of course.)



openssl pkcs12 (export) by default encrypts the privatekey (in a PKCS8 'bag') using the scheme pbeWithSHAAnd3-KeyTripleDES-CBC defined in PKCS12 aka RFC7292 appendix C which uses 3-key TDEA aka 3DES (as it says) and the PBKDF defined in appendix B with SHA-1, 2048 iterations and 8-byte salt; this doesn't appear to have an official name so I just call it PKCS12PBKDF. This seems to be an unwritten convention; all other programs I know of that create PKCS12 also use this scheme, at least by default and sometimes unconditionally. In OpenSSL you can use -key_pbe to specify any (other) PKCS12 scheme (or any PKCS5v1 aka PBES1 scheme, but don't because they're all obsolete and broken) or the PKCS5v2 PBES2 scheme with any supported cipher (in CBC mode) but always with PBKDF2, SHA-1, 2048 iterations, and salt. Although PBKDF2 is technically different from PKCS12PBKDF, the differences don't matter to security AFAICS.

This fixes the most glaring flaw in OpenSSL's 'legacy' PEM-file encryption, that it uses only one iteration of MD5. (Using MD5 is not a problem in itself; although MD5 is badly broken for collision, that doesn't apply to a PBKDF. But since the letters MD5 now provoke irrational panic in checklisters, managers, and other fairy-dust believers, and we have better hashes available, we use them.) But 2048 iterations is not great; it was considered adequate when PKCS5v2 was published back in 2000 but hardware has improved a lot since then and nowadays 10s or 100s of thousands are usually preferred, and some go for millions or more. More importantly, hardware has changed to make raw computation more available in the form of GPUs, FPGAs, and even ASICs, so nowadays an iterated hash is no longer best practice; instead we want a 'memory-hard' function like scrypt or Argon2; see e.g.:
In 2018, what is the recommended hash to store passwords: bcrypt, scrypt, Argon2?
Are there more modern password hashing methods than bcrypt and scrypt?
Is bcrypt better than scrypt
Do any security experts recommend bcrypt for password storage?
How to securely hash passwords?
Why are salted hashes more secure for password storage?
How are SCrypt's memory-hard requirements substituted with more CPU?
Has scrypt been broken, finally?

If you want the most secure private key encryption in OpenSSL 1.1.0 up (these versions are now widespread though not everywhere) use openssl pkcs8 -topk8 -scrypt plus optionally -scrypt_[Nrp] $val if you want to customize although the defaults should be satisfactory. Note however this is not necessarily portable to anything other than OpenSSL. You can also use PKCS8 with PBES2/PBKDF2 but increase the iterations (an option not available for the pkcs12 command) with openssl pkcs8 -topk8 -v2 $symmcipher -iter $num; this is much more interoperable and probably secure enough (given a good password and a decent $symmcipher). (As I noted on a different answer to the Q you link.)

  • Very good answer! pkcs8 -scrypt is exactly what I need. But, are you saying that PBKDF2 (with SHA1 and 2048 iterations) isn't more secure than PKCS12PBKDF? What if you do openssl pkcs12 -keypbe AES-256-CBC -certpbe AES-256-CBC -macalg sha512? Still worse than pkcs8 -scrypt I suppose due to the low number of iterations? – arcus_mannen Nov 8 '20 at 7:33
  • Yes, I see no security difference between PKCS12PBKDF and (PKCS5) PBKDF2 for the same hash&iterations. All pkcs12 options are iterated hash and thus not as preferred as scrypt because BOTH (1) only 2048 iterations AND (2) not memory-hard. – dave_thompson_085 Nov 9 '20 at 0:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.