When a PKCS12 file is imported into a Web browser or Windows store the user is prompted for private key password. How does the browser or operating system manage this password? Is it secure?
2 Answers
The password you are prompted for is the one used to lock the PKCS#12 file itself. PKCS#12 files are really rather generic archives, extensible in many ways, but in practice they are password-protected containers for private keys and certificates. The "password protection" really is password-based encryption: the password is turned into an encryption key using a Key Derivation Function -- in that case, it is PBKDF2.
PBKDF2 attempts to protect the password against brute force attacks by being inherently slow -- by using many internal iterations. The number of iterations is configurable, and was chosen by the system that generated the PKCS#12 file; a higher number of iterations implies higher security (since it makes each password try more expensive) but also higher usage cost (since it makes each password try more expensive).
In any case, once the password has been asked from the user, and turned into an encryption key with PBKDF2, the PKCS#12 file contents are decrypted (in the RAM of the computer). What happens afterwards is completely unrelated to the PKCS#12 file: that file is merely a transport vessel; once your computer has the private key in its RAM, the PKCS#12 file (and its password) ceases to be of any use. Since you are doing an import, your browser or operating system is taking charge of the storage and protection of the private key, and does so using methods that are in no way impacted by the PKCS#12 file or its password. Windows (hence Internet Explorer) will try to store the private key encrypted with your session password, though you can add an extra password.
From a high-level point of view, if you are importing a private key in your machine, then this means that:
- the key is morally yours;
- and yet it was generated elsewhere.
In general, this kind of things is considered suboptimal. If the key is yours, then it should have been generated in your own computer, and the private key should never have left it. The recommended PKI usage scenario is that you generate your key pair on your computer, send the public key to the CA (as part of a certificate request), and receive back the newly issued certificate. In that scenario, only public information travels, and there is no PKCS#12 file at all.
- 320,799
- 57
- 780
- 949
-
Thanks Thomas but I am already familiar with PBKDF concepts, my question is for sure less interesting, I wonder how precisely Windows manage the private key ? I can't imagine an OS or a browser keeping the private key plain text on disk. If the private key is still protected by the initial password, how is managed the password I was prompted ? The "session password" acting as encryption key is the kind of things I am looking for. – crypto-learner Feb 06 '15 at 16:15
-
1Windows, mostly, tries to keep the private key encrypted with a key derived from the current session password; it also periodically moves and reencrypts it, as an attempt at winning some sort of hide&seek game with poorly developed malware. Lookup DPAPI -- the mechanism for private key storage is mostly the same. The important point here is that the password you are prompted for, to open the PKCS#12 archive, is unrelated to all of this. – Thomas Pornin Feb 06 '15 at 17:30
-
If you create the PKCS#12 with openssl, by default the encryption key for the certificates (RC2 40-bit encryption) is derived from the password using PKCS#5 v1.5, and encryption key for the private key (3DES encryption) from the same password using PKCS#12 PBE. You have to ask for PBKDF2, cf. https://www.openssl.org/docs/manmaster/apps/pkcs12.html. – Jim Flood Sep 07 '15 at 21:02
To add to Thomasm Pornin's answer, consider a PKCS#12 that was created by OpenSSL to hold one or more certificates and a private key.
The certificates will be encrypted as a set, by default using RC2 with a 40-bit key ("rc2-40-cbc"
). The key is derived from the password, an 8-byte random salt, and 2048 iterations of SHA1 using PKCS#5 v1.5 ("PBE-SHA1-RC2-40"
).
This simply combines the password bytes and salt bytes and recursively computes the SHA1 hash. The first five bytes of the final hash is the RC2 key, and the next eight, the IV.
The private key will be encrypted by default using 3DES ("des-ede3-cbc"
). The key is derived from the password, an 8-byte random salt (which is different that the salt used for the certificates), and 2048 iterations of SHA1 using PKCS#12 PBE ("PBE-SHA1-3DES"
). This is a little more complicated.
It derives the key and IV separately from different, known starting points. It also converts the password to big-endian Unicode. But more or less, it's a recursively computed SHA1 hash and the first bytes of the final hash give the key or IV.
You have to specifically ask OpenSSL to use PKCS#5 v2.0, a.k.a. PBKDF2, for example on the command line with keypbe alg
, and/or certpbe alg
:
these options allow the algorithm used to encrypt the private key and certificates to be selected. Any PKCS#5 v1.5 or PKCS#12 PBE algorithm name can be used (see NOTES section for more information). If a cipher name (as output by the list-cipher-algorithms command is specified then it is used with PKCS#5 v2.0. For interoperability reasons it is advisable to only use PKCS#12 algorithms.
The PKCS#12 file itself is not encrypted. You can read it and find the PBE and ciphers used in both cases (for certificates and private key). You also can read both salts and iteration counts. So, your private key is only as safe, as from a brute force attack knowing the PBE, the salt, the iterations, the cipher, and the ciphertext. Still, that is a pretty big hurdle to get over.
Note: You might have trouble importing the default PKCS#12 from software that is FIPS-140 compliant because it does not like PBE-SHA1-RC2-40. OpenSSL has a command line switch descert
to ask for PBE-SHA1-3DES for the certificate encryption (cf. above link).
- 121
- 1