3

I know next to nothing about cryptography, and I'm basically just looking for someone to look over what I'm doing and tell me if I'm screwing up.

I have the user entering in some sensitive information and a password. I then use that password as a key for AES to encrypt the information and store the ciphertext. Later, if the user wants to retrieve the information, they reenter the password and I use AES to decrypt the ciphertext.

Is this secure? Right now I'm just using the password directly as the encryption key. I've seen PBKDF2 mentioned a lot in similar contexts, but I'm not sure what the point of it is. I'm never storing the password anywhere. If the user forgets their password, the information will just be lost forever.

If possible, I'd like to be able to store the ciphertext in the cookies of a web browser (though this isn't totally necessary), so it's important that the information be secure.

Implementation notes:

I'm using CryptoJS, which I believe randomly generates the salt and IV. I don't know the details really, it just seems to do everything for me.

Part of the information I'm storing is the user's name, so I don't know if that opens me up to a known plaintext attack or something.

2
  • May the user change the password ? In such scenario, all the cyphered data would need to be ciphered again using the new password, which may or may not be an issue depending on your needs. Nov 13, 2013 at 11:00
  • No, the user man not change the password. The user can reenter the old data with a new password though
    – sjelin
    Nov 13, 2013 at 17:08

2 Answers 2

4

The answer is in the name: PBKDF is an acronym standing for "Password-Based Key Derivation Function". Its whole job is to take a password as input and generate an encryption key as output.

The primary reason we need functions like this is that encryption algorithms like AES take a fixed size key. By definition, AES-128 requires a 128 bit (16-byte) key. But a user's password is simply a series of bytes - maybe it's 50 bytes, maybe it's only 5 bytes, depending on what the user entered. Therefore, if you want to use the password to encrypt, you somehow have to embed that password into the exact 16 bytes required by AES. You're obviously doing something like that already in order to feed your current password into AES, even if you don't recognize it by that name.

A PBKDF is designed to take however many bytes the user inputs, stir them all together using an algorithm (called a hash), and then produce a string of bits suitable for use as a key. If you need 16 bytes for your AES key, you simply take the first 16 bytes that come out of the PBKDF function.

Think about if you didn't use a PBKDF, but instead required your users to enter at least a 16 byte password. Without a PBKDF, what happens to everything after the 16th byte? It becomes meaningless. If I type a password of security.stackexchange.com, I could also type a password of security.stackexPOSITION@ORG or just security.stackex and any of them would still work. But because a PBKDF mixes all of those letters together, they all contribute to the key, and the whole password is checked.


The next reason we need PBKDF functions is that passwords have a lot of predictability in them, because English-speaking humans usually only use characters in the ranges of a-z, A-Z, and 0-9. Despite the fact that there are 8 bits in a byte, a 10 character password will not provide 80 bits of uncertainty in the key; most will provide 47 bits (or less) of uncertainty, and that means it can be easily guessed by a modern attacker. But because a PBKDF takes all the letters of the password into account, it makes a 20 character password much stronger than a 10 character password, and improves your users' security.


A stronger routine such as PBKDF2 goes one step farther than a simple PBKDF in helping protect against a password guessing attack, by making the operation take a large amount of computing resources. An attacker who wishes to try guessing every word in the dictionary will need only a few milliseconds to try every word as a decryption key. An attacker who needs to run through 10,000 hashes with PBKDF2 will take hours or days to try the whole dictionary.

1
  • Thanks! It looks like CryptoJS by default made a key out of a password using openSSL. I'm using PBKDF2 now with 50000 iterations.
    – sjelin
    Nov 14, 2013 at 20:54
0

As far as I know, this should be okay.. I did similar thing in PHP for simiar task. What's more, the user's memory is one of the best places to store the AES key. Or at least part of it. You know, because if you'd store it in database or a file on the server, once the database or the server is under attack, the data is no longer secure.

I'd make sure the user's password is strong enough and random enough. I'd implement some usual checks for uppercase letters, numbers and also dots or something. The user should know this is the password used to store his data and it should be different from the pasword he uses to log in (if you have something like that). And also the salt (or the second part of the key) should be stored securely, e.g. also AES'd in the database with key stored on the server. Something like that.

To simplify the pbkdf, if I understand it correctly: It is a way to "convert" the user's password to the actual encryption key. So if you use that in connection with AES, that'd be the best.

Another thing I'm sure is that some of the experts here would point out more drawbacks of this approach. However, I think AES is secure enough for coming decades. Guys from 1Password seem to think that too.

6
  • I think you're misunderstanding. I'm never storing the key anywhere. The user just has to remember it. If they forget their password, the information they entered is just lost. They'll have to reenter it. Also, aren't salts allowed to be stored in plaintext?
    – sjelin
    Nov 13, 2013 at 6:44
  • I get that PBKDF makes keys out of passwords, but what I don't get is why the password can't be used as a key directly.
    – sjelin
    Nov 13, 2013 at 6:46
  • Yeah.. because person can only remember short password, under 20 characters long.. And the key should be longer than that. Right? Nov 13, 2013 at 6:48
  • Because the key for aes needs to be of arbitrary length (fixed amount of bytes) you use pbkdf2 to truncate the password. And you are correct the salt isn't secret. Nov 13, 2013 at 6:50
  • 1
    Before claimi g it's safe, it's important to check what encryption mode is in use, how the IV is generated, and how integrity is ensured. Screwing up any of those three things can destroy the security of an otherwise secure system
    – atk
    Nov 13, 2013 at 13:08

You must log in to answer this question.

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