3

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.)

1 Answer 1

5

Some.

openssl pkcs12 -export through 1.1.x 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. (Update: after 2020 this started to change; some other things now use PBES2 almost always with AES.) In OpenSSL you can use -keypbe to specify any 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, (corrected) SHA-1 through 1.0.x or SHA-256 in 1.1.x up, 2048 iterations, and salt. Although PBKDF2 is technically different from PKCS12PBKDF, the differences don't matter to security AFAICS. Update: 3.0.0 (released in 2021) up defaults to PBES2 with SHA-256 and AES-256, although you can specify -legacy [-descert] to go back to the long-conventional PKCS12 schemes (SHA1 and 3DES for key, either that or SHA1 and RC2-40 for cert).

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?
https://crypto.stackexchange.com/questions/959/strength-of-multiple-hash-iterations
https://crypto.stackexchange.com/questions/12795/why-do-i-need-to-add-the-original-salt-to-each-hash-iteration-of-a-password
https://crypto.stackexchange.com/questions/3252/is-bcrypt-better-than-gnuppgs-iteratedsalted-hashing-method
https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512

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 with openssl pkcs8 -topk8 -iter $num (1.1.x up defaults to PBES2/SHA-256/AES-256 but for 1.0.x or lower specify -v2 aes-256-cbc or similar); this is much more interoperable and probably secure enough (given a good password). (As I noted on a different answer to the Q you link.) Update: as @muxmuse comments, for 3.0.0 up pkcs12 -export also supports -iter N -- and as noted above also defaults to PBES2/SHA-256/AES-256.

4
  • 1
    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? Nov 8, 2020 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. Nov 9, 2020 at 0:06
  • -iter was added to the pkcs12 command
    – muxmuse
    Nov 7, 2023 at 16:37
  • @muxmuse: and that's not the only change; editted. Thanks for reminding me. Nov 8, 2023 at 8:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .