8

Imagine I have a website with user accounts. I want to authenticate users, so I need to know if the password they provide matches the one stored in my database. To protect the passwords from prying eyes, I want to obfuscate them, I decide to use AES in CBC mode to do so.

I know that I shouldn't use AES-CBC to do this, and probably should go with a hashing algorithm instead of an encryption one, but please, ignore this fact. It will help me understand things better if you do.

When encrypting the user password to store it in my database using AES-CBC, do I need to use a Key, an IV and a Salt? Whatever I need to use, how would they be used exactly?

I'll give an example to better explain my issue:

A user with username "bob" signs up with the password "mypass"

I need to decide what is the safest way to obfuscate this password using AES-CBC.

Right now I think to do this I need to generate a 16-byte salt using a CSPRNG[1]. Than I must prepend the salt with the user password: salt+"mypass". Than I must encrypt salt+"mypass" using AES-CBC which I will use a hardcoded 256 bit key and a randomly generated IV of 16 byte.

Effectively I have: AesEncrypt(salt+"mypass", GenerateIv(), Key)

Given this example, I have a few points which confuses me.

1) The random IV I am passing to AES will have the effect that no two "mypass" gives the same ciphertext. Doesn't this make the salting redundant, because the point of the salt is to prevent two ciphertext of the "mypass" to be identical?

2) Inversely, could it be that the IV is redundant, and I could just pass in the zero IV or a constant IV since I am salting my passwords?

3) Say the IV and the salt are not redundant, because somehow I read without really understanding that the IV is XORed but not the salt, making both useful. Is it enough for me to properly salt to simply prepend "mypass" with the salt?

4) Am I somehow supposed to use the salt to derive the key that I will use for encrypting "mypass" with AES? Or am I doing it right by simply using a hardcoded key?

5) What am I supposed to store in my database? Should the salt, the iv and the ciphertext all be stored in individual columns, or should they be somehow combined together, if so, is simple concatenation enough, or they must be combined with a special function?

6) Am I completely wrong and if so, what should I do instead?

Thank You.

=============

[1] cryptographically secure pseudo-random number generator

6
  • 5
    You explicitly asked that we ignore the fact that you are not using the right tool (hashing), so I post this as a comment. Having compromised the server, the attacker has access to your AES private key and can decrypt all passwords. If this is out of scope for your scenario, you should better define the threat model. Mar 8, 2014 at 13:10
  • @YolandaRuiz It's more that I'm trying to understand the role of the IV versus the role of the salt. When it's AES-CBC, the IV seems to me as if it is exactly applied like a salt would, but this is just my intuition telling me. I know it's used to prefill the initial matrix, so that the first thing you are encrypting is the random IV, which also makes every other block to be encrypted differently. I feel like the IV is a standardized salt, where the salt is manually applied, the IV is taken care of by the implementation of CBC itself. That's why I want to ignore the rest of the scenario.
    – Didier A.
    Mar 10, 2014 at 14:51
  • @YolandaRuiz On the other hand, I am also interested by what you mention here. When you pre-compute a rainbow table, you need to be able to perform the encryption on your own side, which I'm guessing, requires the key. But as you say, in AES, once you have the key, you can simply decrypt the database. So maybe in my scenario, the IV and the Salt serve no purpose, because if you are able to pre-compute, it also means you are able to decrypt, which makes pre-computing useless and the extra protection of IV and Salt useless. Is this right?
    – Didier A.
    Mar 10, 2014 at 14:54
  • You are using the wrong tool, you should use scrypt or similar to store user passwords
    – miniBill
    Mar 13, 2014 at 8:40
  • The hard part in data security is not encryption or hashing, it's key management. That's the main reason why you never want to use encryption when a HMAC will do.
    – Stephane
    Mar 13, 2014 at 8:57

2 Answers 2

1

You are correct in that the salt and the IV are redundant: they both protect against the same type of attack (discovering that two accounts have the same password), and they do it in the same way (by making the encrypted representations of the password differ).

2
  • Is one preferable over the other for AES-CBC. I've read CBC mode has strict requirements on the IV, it must be cryptographically random (unique, random and unpredictable). If I don't use an IV, and instead use a Salt, does my salt needs to meet those same strict requirement, or can it just be unique and random, meaning a non cryptographically secure random generator would suffice?
    – Didier A.
    Mar 10, 2014 at 14:35
  • 1
    I'd go with changing the IV, simply because it's the better-studied option.
    – Mark
    Mar 11, 2014 at 20:58
9

When encrypting the user password to store it in my database using AES-CBC, do I need to use a Key, an IV and a Salt? Whatever I need to use, how would they be used exactly?

The IV is used to initialize the first 16 byte matrix of the AES-CBC encryption scheme. It is XORed with the first 16 byte of the message. This means that, if the IV is constant, the same message will always output the same ciphertext. On the other hand, if the IV is different on each encryption run of the same message, because of the XORing of the IV with the first block, the ciphertext will always be different, since the result of the XOR will be different. IV is an inherent part of AES-CBC, and you will always have to use an IV, the choice is whether this IV is constant or not.

The Salt is a random message that you prepend to the real message so that on every encoding of the real message, you are actually encoding a different looking message (salt + real message) which will result in a different ciphertext. This is normally used for hashing algorithms, in order to get a different hash on each run of hashing of the same message.

You do not need to use a salt with AES-CBC, because the IV is already having the effect that the salt is designed to have. But if you want to use a salt, you can, and here is what would happen. Say you had a 16 byte salt, it would be prepended to your message, so you would have (salt + message) as the input to be encrypted by AES-CBC. Being 16 byte, your salt would fit in the first block of AES-CBC, it would XORed with the IV and as a result you would have (salt XOR iv). This result of (salt XOR iv) would then be used as the IV for the second block, which in this case, would be the 16 first byte of the real message.

Therefore, in the case of AES-CBC, using a salt only has the effect of an extra processing on top of your IV. If your IV is constant, the salt will XOR with it, resulting in a new IV to the second block that is different for each run of the encryption, even though the IV is constant.

So in conclusion, you are better of just using a random IV and not using a salt at all. Or use a constant IV and have a random salt (but watch out for this, go see #2 below for details). Both of these will have the same effect, which is to generate a different ciphertext on each encryption run of the same message.

1) The random IV I am passing to AES will have the effect that no two "mypass" gives the same ciphertext. Doesn't this make the salting redundant, because the point of the salt is to prevent two ciphertext of the "mypass" to be identical?

Yes it does. The IV and the salt effectively have the same effect, and help protect against the same attacks. Do note that, for the salt to have the same effect, proper thought in it's implementation must be considered, see #2 below for more details.

2) Inversely, could it be that the IV is redundant, and I could just pass in the zero IV or a constant IV since I am salting my passwords?

Not so fast. A lot of things must be put together properly for this to be true. Depending on the mode of AES, it might not always be true that the salting will result in the desired behaviour. Your salt length and the way you concatenate it with your message must also be right, appending could lead to problems for long passwords for example. Therefore, it is better to use the AES as it was thought of, that is, use a random IV and no salt.

3) Say the IV and the salt are not redundant, because somehow I read without really understanding that the IV is XORed but not the salt, making both useful. Is it enough for me to properly salt to simply prepend "mypass" with the salt?

The IV is XORed with the first block of AES in mode CBC to be encrypted. If you use a salt, the salt will be XORed with the IV in the first block, and this (IV xor Salt) will effectively become the IV of the second, which given a 16 byte salt, would be your actual message to be encrypted.

4) Am I somehow supposed to use the salt to derive the key that I will use for encrypting "mypass" with AES? Or am I doing it right by simply using a hardcoded key?

You shouldn't ever derive the key from the salt. The salt is not secret, and therefore, if you were to do that, the key would be easily found from the non secret salt. I was getting this confused with password based encryption, where you use a key derivation function to derive the key from a secret password.

5) What am I supposed to store in my database? Should the salt, the iv and the ciphertext all be stored in individual columns, or should they be somehow combined together, if so, is simple concatenation enough, or they must be combined with a special function?

From what I understood, this doesn't matter, as long as you know how to retrieve them. You can either use different column, or combine them together in one somehow.

6) Am I completely wrong and if so, what should I do instead?

Basically, I am using AES-CBC as a hashing function. Where normally the 256 bit key of AES means it is very hard to brute force, this bypasses that because here you can brute force the combination of the message, since the message is a password, chances are it's a lot shorter than 256 bits to brute force.

The other issue is that, being a symmetric algorithms, if a hacker compromises the server, and gets the key, he does not even need to brute force, dictionary attack, rainbow table, or anything else, he can just decrypt all passwords.

2
  • Your answer to #2 depends on both the block cipher mode ( will work with CBC mode, but not CTR mode) and that the unique salt is prepended to each password (if the salt is appended to the ends of passwords, its likely you will leak information on long passwords that have matching first blocks). And with modes like CTR, reusing an IV (even with a varying salt) is completely insecure -- this is the equivalent of reusing a one-time-pad. To summarize, its best to use encryption as intended. That is use salts for hashed pws, and secret keys and random IVs for encrypted pws.
    – dr jimbob
    Mar 12, 2014 at 18:23
  • @drjimbob Thanks, made some edits to emphasize that fact.
    – Didier A.
    Mar 12, 2014 at 20:56

You must log in to answer this question.

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