TX_
TX_

Reputation: 5476

Is it ok to derive initialization vector from password (as with key), given the salt will be random?

Cryptography gurus please help.

I've learned that encryption key with symmetric algorithms (e.g. AES) should be derived from password via the PBKDF2 function, using the random salt in each encryption. I've also learned that IV should not be hard-coded, or directly bound to (derived from) password string or encryption key. Until now I was generating both key derivation salt and IV randomly, 16 bytes each for my AES-256 encryption, and storing them along with encrypted payload.

Now I'm thinking random-generation of IV is redundant, if I use random salt, as I can derive both key and IV from password string with that salt. Or maybe I shouldn't?

So my question is ultimately this:

Can I derive initialization vector from password (as I do with key), or should I generate random IV each time, given the fact that I use random salt in each encryption?

So can I use the below C# code?

// Derive key and initialization vector from password:

// ---> NOTE: _salt is random 16 bytes in each encryption.

byte[] key, iv;

using (Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(password, _salt, _iterations))
{
    key = derivedBytes.GetBytes(32);
    iv = derivedBytes.GetBytes(16);
}

Upvotes: 4

Views: 3520

Answers (4)

Maarten Bodewes
Maarten Bodewes

Reputation: 94058

Yes you can use it that way, as long as you never ever use the same salt for the same password (even in time) to calculate the key and IV. The IV only has to be unique when you encrypt with the same key, and you would calculate a new key each time. In principle you could even use an all zero IV, as the key is never repeated, but you are better off using a derived one.

Note that if one of your colleagues decides that PasswordDeriveBytes - the broken implementation of PBKDF1 from Microsoft - would be better suited for the task, then you may very well be vulnerable to all kinds of attacks. This is just an example what can go wrong if your security margins are tight...

Fully random IV's should certainly be preferred.

Upvotes: 4

jbtule
jbtule

Reputation: 31809

The most important part of semantic security for the initialization vector when using AES-CBC is that it should not be predictable.

With your suggested implementation a given key will always have the same initialization vector, but you wouldn't be using the same keys because of your 128 bit salt. Seems pretty unpredictable, that said, it's not a best practice, and generally when you do something clever to save 16 bytes of space your are losing some security of some sort or opening yourself up to some unknown attack vector.

I think you should use RNG and take the space 16 byte hit, being conservative is the name of the game when dealing with encryption. There are other things such as authenticated encryption that you should probably look into as well, I have an example implementation on codereview.

Ultimately there are other things that are important that provide additional overhead beyond the iv for security such as authenticated encryption, versioning, and keyrotation, and there really haven't been any high level encryption frameworks for C#. I've been working a C# implemenation of Google's Keyczar framework. You can follow it, if you like, on github Keyczar-dotnet. It's pretty much feature complete, and has 90% test coverage, but conservatively, I wouldn't recommend using it until it gets officially accepted as part of the project, and then will likely have a larger group of eyes on it in the future.

Upvotes: 0

rossum
rossum

Reputation: 15693

The more links there are between different parts of any crypto system then the easier it will be for any attacker to use those links as a back door from one part of the system to another. Remember that the IV is sent in the clear while the key must be kept secret, so any sort of link between them is a huge risk to take.

Use Rfc2898DeriveBytes to generate your key and use a good crypto RNG to generate the IV. Remember that the attacker will see the IV so there is no need to go through the full RFC 2898 process. Use the standard crypto RNG for the IV that will probably be faster than the RFC 2898 process because it does not have the iterations.

Upvotes: 0

akton
akton

Reputation: 14386

What do you mean " using the random salt in each encryption"? It is best to derive the salt and IV randomly, such as the output from a cryptography standard random number generator and store it with the derived bytes. Generate a new IV and salt for each password.

Why from a cryptography standard RNG? Deriving from the password means any weakness in the derive bytes function is reflected in both the bytes and the IV. It is not difficult in modern programming languages to generate it from a RNG and using a RNG ensures the IV for new passwords encrypted is not predictable. There are probably better reasons but I am drawing a blank.

Upvotes: 0

Related Questions