Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I'm writing some software where I have to encrypt all files that are written to a specific folder using AES. There is one password/key that is configured somewhere, that is always used.

I don't want to store a base64 string because that is too complicated for the person who might have to change the configuration. I want to store a string containing any characters. What is the best way to convert this password to a key for use in AES?

  • Can I just get the bytes from the key?
  • LShould I generate a key using PBKDF2?

As I understand, I then also need to provide a salt. However, in my situation the salt seems unnecessary because I only have one key.

  • Do I just provide an empty salt or is that somehow not secure?
  • Or is there a completely different (hopefully simpler) way?
share|improve this question
1  
"If you are typing A E S you are doing it wrong": cs.berkeley.edu/~daw/teaching/cs261-f12/misc/if.html –  adric Jul 15 '13 at 12:04
    
All the below solutions seem to be way above my head. Taking the above comment into consideration, I decided to just store the whole 256bit key as a hex string. The question might still be relevant for someone else though, so I'll leave it in its current form. I don't know how to choose to accept an answer though, but upvotes do their job quite well I think. –  Matthijs Wessels Jul 18 '13 at 14:46
add comment

3 Answers

What you do is the following:

  • Generate a long key (this is just a randomly generated amount of bytes in hex, you can use 128 bytes)
  • You use this key to encrypt your file with AES (meaning you use it as a password)
  • You encrypt the key itself with AES using your password (which is a bit shorter but easier to remember. Now AES requires this again to be either 128, 192 or 256 bits of length so you need to make your password of that length. Hence you can just use PBKDF2 (or scrypt or bcrypt) to create a fixed key length from your password. DO NOT STORE THIS.
  • You keep a hash of your hashed password using PBKDF2 (or bcrypt or scrypt). This will allow you to check if the password is correct before trying to decrypt your encrypted key.

So:

hash(hash(password)) --> can be stored
hash(password) --> cannot be stored

You always need to provide a salt even if you only have one key (this largely prevents rainbow table lookups). Fortunately for you, salt generation is done automatically by PBKDF2.

So in the end you actually have 3 things:

  • Your encrypted files
  • Your encrypted key
  • A hash of your password to verify it

You might ask why you need the key: If you would change your password (and you had encrypted all your files with your password), you would need to first decrypt all your files with your orignal password and then re-encrypt them with your new password. With this implementation all you need to do is decrypt and re-encrypt the key (as this key serves as your password).

EDIT

I kind of misinterpreted your question, I've added the key derivation function.

Also a good read (courtesy of IBM)

share|improve this answer
    
Yea I misinterpreted the question, I'll edit –  Lucas Kauffman Jul 12 '13 at 17:22
    
@LucasKauffman +1 for the salt, horray for salt! Isn't salt when used in the context of a reversible algorithm called an initialization vector? That's how I have understood it, same thing different name. –  Four_0h_Three Jul 12 '13 at 17:41
    
Well you shouldn't store it, I've added it to the answer –  Lucas Kauffman Jul 12 '13 at 17:57
    
@LucasKauffman Ah I see. I didn't realize you were hashing the hash. –  Brendan Long Jul 12 '13 at 18:00
1  
@PsudeoReality the IV is different from the salt actually –  Lucas Kauffman Jul 12 '13 at 18:05
show 1 more comment

If you generate a key you should somehow hash it, considering that a hash function is "sort-of" like a pseudo-rng. So using PBKDF2 is always good, since it is a key derivation method and is used specifically for this purpose. You pass in a password, and it generates a key you can use based on your password and a salt. As far as Salt, it is automagically part of PBKDF2 so you shouldn't have to worry about it.

If you use something like .NET and store the key in your web.config file you can encrypt parts of your web.config with either the machine key or an RSA key http://msdn.microsoft.com/en-us/library/dtkwfdky%28v=vs.100%29.aspx , the nice thing about this is that windows will take care of storing the RSA key and or machine key. You can even automate this process with your build server.

share|improve this answer
1  
You would need to re-hash the key you derived with PBKFD2. Otherwise you store the decryption key directly with your encrypted files. –  Lucas Kauffman Jul 12 '13 at 12:09
add comment

To convert a password to an AES key, PBKDF2 is the simplest way of handling it. Just make the sure the password has sufficient entropy.

You do need to use a salt, because it's there to protect against rainbow table attacks.

Depending on your platform, there may already be libraries available to help with this. If not, I'd recommend something close to Lucus Kaufman's solution.

Setup:

  1. Generate a random 128-bit key (k1), a random 128-bit IV, and a random salt (64 bits is probably sufficient).
  2. Use PBKDF2 to generate a 256-bit key from your password and the salt, then split that into two 128-bit keys (k2, k3).
    • Make sure your algorithm's native output is at least 256 bits, or this will be slow. PBKDF2-SHA256 is a good choice. Don't use two seperate algorithms for this, since it will just make it slower and more complicated for you, but won't slow an attacker down.
    • If your password already has sufficiently high entropy, then you can afford to use a fairly low number of iterations. 1000 iterations will be so fast you won't even notice it (especially since you'll only need to decrypt the key when the program starts up), so there's not much reason to go below that. If your password is weaker, you can turn up the number of iterations to compensate.
    • I don't recommend using bcrypt for this, since it's output is the wrong size and you would need to hash it again, which adds unnecessary complexity.
    • I think scrypt can generate arbitrary-sized output, so it would be a good choice if it's available (this may not be allowed if you want FIPS compliance).
  3. Use k2 to AES encrypt k1 using the random IV.
  4. Save the encrypted key, k3, the salt and the IV to a file somewhere.

Encryption / Decryption:

  1. Use PBKDF2 + your password and the salt from the file to regenerate k2 and k3.
  2. Verify k3. If it doesn't match, either your password is wrong, or someone tampered with your file. Stop here.
  3. Use k2 and the IV from the file to decrypt k1.
  4. Use k1 to encrypt or decrypt files.

Password Change

  1. Decrypt k1 as in the Encryption / Decryption section.
  2. Follow the steps in Setup, using the same k1, but regenerate everything else (new random salt and IV, generate k2 and k3 from the new password).

Do not store k2 anywhere. Do not store k1 unencrypted. Doing either of those things will break the security of your system.

If you don't care about being able to change your password (I would consider this a very important feature, but maybe you don't), then you could skip the steps involving k1, and use k2 as your AES key and k3 to verify it.

You may also find it useful to generate another key for HMAC, so you can verify that the encrypted files haven't been tampered with. If you want to do that, you can generate a 128-bit HMAC key, and encrypt and store that with the main AES key.

share|improve this answer
    
The password is not entered from outside of the webapp but just stored in the configuration. So I don't think I need to check if the password is correct. –  Matthijs Wessels Jul 18 '13 at 20:48
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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