11
$\begingroup$

I would like to know how to store a sensitive file; a credential of sorts. I want to password-protect it, obviously. It would be appropriate - in my application - to prompt the user for the password each run. There are proper apps - like SSH - that password-protect private keys and so on, and that's the model and best-practice I'd like to follow.

What is the best-practice for encrypting small files? I'm thinking of generating a random key to encrypt the file with and using a block cipher. And then encrypting this random key with the user's password, and trying to salt and stretch that password.

In the same way that storing password hashes is something you should turn to a proper 'stretching' function like bcrypt/scrypt/PBKDF2 (ideally via a library like Python's passlib) rather than rolling your own, are there proper algorithms and libraries for password-protecting files?

$\endgroup$
0

4 Answers 4

9
$\begingroup$

The most important best practice in cryptography is: Don't invent your own algorithm, and to a lesser degree, don't invent your own protocol. An encrypted file format is a protocol.

Use an established format, like the OpenPGP message format, for your files. (This does support password-based encryption, too.)

This has the main advantage:

  • You can be quite sure that it is correct, i.e. no mistakes in the design which would allow easy cryptanalysis. (Not 100% sure, but at least a lot more eyes looked at it than will ever look at your own protocol.)

Another nice bonus is that your customers then are able to use the encrypted files also without your program, if necessary (e.g. when your program is not available on the system, has bugs, gets lost, or similar).

$\endgroup$
2
  • 1
    $\begingroup$ +1 for linking to a complete interoperable best-practice standard for encrypting files -- OpenPGP -- rather than mentioning one particular primitive or another, which all too often are used incorrectly or at least in unnecessarily incompatible ways. $\endgroup$
    – David Cary
    Commented Nov 13, 2012 at 13:21
  • 2
    $\begingroup$ As of 2019, the OpenPGP message format is not recommended, as it doesn't support modern key stretching functions. Using the scrypt libraries and file format is a better choice. $\endgroup$
    – mihao
    Commented Aug 20, 2019 at 4:17
5
$\begingroup$

A properly salted cryptographic hash of the password, generated through a secure and slow algorithm such as bcrypt or scrypt, could be directly used as your key (assuming they have the correct size). Salts can be generated randomly on encryption and should be included with the ciphertext.

Bcrypt, for instance, generates a hash of 192 bits (if I am not mistaken); so you could use it directly as an AES key.

If the hash is longer than the size of the key of the desired encryption algorithm you should simply be able to take the first n bits of the hash.

Only encrypting a random key with your password, as you describe, is a redundant extra step that doesn't really add any security.

$\endgroup$
3
  • 2
    $\begingroup$ +1 In fact, deriving encryption keys from passwords is the primary purpose of PBKDF2 and its ilk; the name stands for Password Based Key Derivation Function, version 2. The fact that they can also be used for user authentication is just a side benefit. $\endgroup$ Commented Sep 7, 2012 at 20:53
  • $\begingroup$ Ps. While encrypting a random key with the password-derived key indeed doesn't provide a security benefit, it can be convenient if you ever want to change the password (or allow the file to be decrypted with more than one password or other key). $\endgroup$ Commented Sep 7, 2012 at 20:56
  • 1
    $\begingroup$ Good point. Altough I do think the case where different passwords are used to encrypt the same file with the same key are relatively rare. Using this method to make changing passwords cheaper might indeed be a pretty good idea when dealing with very large files or entire backups. $\endgroup$
    – AardvarkSoup
    Commented Sep 7, 2012 at 21:17
5
$\begingroup$

Read Try to avoid using passwords as encryption keys.

Deriving a cryptographic key from a password tends to be a major security problem, as in practice, passwords rarely have enough entropy to resist offline dictionary attack.

If you absolutely must derive your crypto key from a password, then for heaven's sake, use a slow hash like PBKDF2. But even then, given what we know about typical user behavior, you should expect that this scheme may not provide strong protection against attack.

(I recommend PBKDF2 instead of bcrypt, as PBKDF2 was designed exactly for this purpose. You might be able to adapt bcrypt to use it for this purpose, but you might have to do a little bit of extra tweaking to disable the salt and make sure you use the proper range of bits of the output of bcrypt.)

$\endgroup$
1
  • $\begingroup$ As of 2019, Argon2 or scrypt should be used instead of PBKDF2 or bcrypt. $\endgroup$
    – mihao
    Commented Aug 20, 2019 at 4:08
4
$\begingroup$

It seems that there are many tools that support strong encryption algorithms, such as AES256, but finding one with a good key stretching function is not so easy. The two standard tools are OpenSSL and GnuPG. However, when it comes to key stretching, OpenSSL 1.1 uses PBKDF2 and GnuPG uses Iterated and Salted S2k, and both are not very resilient to brute-force attacks by modern standards. OpenSSL versions prior to 1.1 cannot perform key stretching at all.

As far as I can tell, Argon2 is one of the best key stretching functions (as of 2019), but I couldn't find any simple utility that would combine Argon2 key derivation with file encryption. scrypt would be my second choice after Argon2, and it does have a tool with a set of libraries for file encryption with an established file format, so that's what I would recommend.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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