6

I start with a weak password (8 lower case characters for ex) and a file. I need to encrypt that file using that password. Result has to be secure against known attacks.

Approach 1: I could hash the password using SHA-256 and then use the resulting hash and file as inputs to AES-256, giving me an encrypted file. I understand that both SHA-256 and AES-256 are very fast. Wouldn't this make the file vulnerable to a brute force attack?

For example, could one grab a rainbow table of pre-computed SHA-256 hashes and, assuming its a really small file and a really weak password, try to AES-256 decrypt using each hash from that table in a reasonable time (a few months with specialized hardware).

Approach 2: Use bcrypt. If I understand correctly, bcrypt is better suited for encrypting files than SHA-256 + AES-256, since it's key generation scheme has a work factor resulting in a stronger key. Or am I wrong?

The Ruby and Python implementations (wrappers?) that I've seen focus on using bcrypt as a hashing scheme for passwords, not a cipher per se. Can I even use bcrypt to hash a weak pass AND encrypt the file in "one step"?

Approach 3: Use bcrypt to hash the pass, use that hash and file as inputs into AES-256, giving me the encrypted file. This takes care of the "key is too fast to generate" problem. (Assuming its a problem.) However, bcrypt hashes are 448-bits long and AES-256 wants a 256-bit key. Naive solution is to simply drop the trailing bits of the hash and use that as the key for AES-256. I would NOT go this route because I don't know enough about cryptography to know what the consequences are.

EDIT: I can't salt the pass, since this is for an offline application. ie. there is no reasonable place to store the salt. I can salt the pass and store the salt unencrypted along with the encrypted file. Salts are almost inherently public/visible if say a database is compromised. Purpose of a salt is to prevent a rainbow table attack. Thanks to Nemo, bellow.

Nick Zalutskiy
  • 14,952
  • 7
  • 53
  • 50
  • All of them sound like a bad idea. If you start with a weak password, any transformations you apply are still going to make a weak password as they will probably be known or rely on obscurity. – Jeff Foster Jun 03 '11 at 15:32
  • I guess the question is what is the most we can offer when the user, against all suggestions, decides to use a weak password. I don't want to require passwords with symbols and CAPS and all that because people forget them, as a rule. – Nick Zalutskiy Jun 03 '11 at 15:42
  • How about leaving that decision to the user, instead of forcing them to use weaker passwords? – Aaron Klotz Jun 03 '11 at 18:36
  • Where did I say that I intend to force the user to use a weaker password? On the contrary, I'm searching for a scheme that would be fairly strong even with a weak password. – Nick Zalutskiy Jun 03 '11 at 19:48

1 Answers1

12

Approach 4: Use PKCS#5 (PBKDF2 for deriving a key from a pass + a cipher of your choice for encryption using that key), preferably somebody else's implementation.

And don't forget the salt. (You store it together with the encrypted data. It only needs to be 8 bytes or so.)

Community
  • 1
  • 1
Nemo
  • 70,042
  • 10
  • 116
  • 153
  • I thought that a known salt is no salt at all. – Nick Zalutskiy Jun 03 '11 at 15:39
  • 4
    You thought wrong :-). Salts are public almost by definition. See [here](http://stackoverflow.com/questions/6141537/how-store-salt-in-distributed-environment/6141693#6141693) for more information. – Nemo Jun 03 '11 at 15:41
  • 1
    You're right. It's the same conclusion I came to a few months ago when researching password hashing schemes, and yet, now, proceded to say what I just said above. [smack forehead] A sign that my brain is turning to mush. =) Thanks! – Nick Zalutskiy Jun 03 '11 at 15:47
  • I see there is also a "work factor" in PKCS#5, so why that over bcrypt then? – Nick Zalutskiy Jun 03 '11 at 15:58
  • 2
    Because it is a widely-used standard using widely-used cryptographic primitives. For example, SHA-256 has received more analysis than Blowfish, which makes it "more secure" in most people's view. But neither has been cracked, to my knowledge. (Using a standard also improves maintainability; it will be easier for people in the future to find implementations for other platforms, if that is ever a concern.) – Nemo Jun 03 '11 at 16:03
  • 1
    I've read the PKCS#5 document and I think this is exactly what I was looking for. As I understand, to conform to the standard, one can use PBKDF2 to generate a 256-bit key and then use that key with AES-256. PBKDF2 itself can use a variety of pseudo-random functions, such as HMAC-SHA-1. In python, one could use this module: https://www.dlitz.net/software/python-pbkdf2/ Same author as PyCrypto. From looking at the source, HMAC-SHA1 is used for the pseudo-random function. – Nick Zalutskiy Jun 03 '11 at 19:57
  • Note that the linked PBKDF2 implementation uses 1,000 iterations by default, this is low on modern hardware. See here: http://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pkbdf2-sha256 – Nick Zalutskiy Jun 30 '11 at 17:02
  • What about using scrypt instead of PBKDF2? –  Nov 23 '16 at 04:45