2

I seen a lot of AES implementation samples wide spreaded over the Internet in almost every language I can recognize. There is one difference that I reflect to be repeated between all.

Some of them are require a IV and a key. Two entities. Some of them reuse a part of the 128 bit key as a IV. One entity (in my eyes).

For instance, this can be found on the net

Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt);  
rijndael.Key = pdb.GetBytes(32);  
rijndael.IV = pdb.GetBytes(16); 

..and the whole sample this part come from is quite wide spreaded. Even in MSDN forums. One other hit on the net with 22 upvotes says "This is plug and play code that I found on internet. It just works:"

This cause me some headache. Is this secure? I can't see why authors bother to create an IV functionality just to see it being shortcut just by cutting key in half to produce a byte array with size that fit IV?

I feel that the question will be more complex because if the different cipher modes use the IV on different way. Also it may be dependent on how the application is built. For instance; is the full key always unique? If not, how is the entropy of the key? And separately, is the pair (iv, password) always unique?

By looking at many of the samples that populate IV with a part of the key, they posted an static 16 byte array with fixed values. No indication or attempt to make audience understand that the sample is expected to be used for random -whatever- keys.

Is it safe to use a part of the key as IV and what is best practice?

5

Is it safe to use a part of the key as IV and what is best practice?

In a word. NO.

IV is a fundamental part of cryptography that forms part of the essential element of randomisation. The use of a non-cryptographically random IV that is static or otherwise predictable as part of your encryption process means that you are potentially weakening the randomisation element of your chosen cryptographic algorithm.

The reason example code frequently uses fixed IVs is for that very reason. It's example code, commonly found in books or on websites. The authors have a need and desire to keep the example code as short as possible, so fixed IVs are used on the unwritten understanding that the reader has a sufficient grounding in the principles of cryptography to know they should be using random IVs in real life.

If memory serves, Bruce Schneier has an entire chapter on IVs in one (or more) of his books. That would be an excellent starting point if you really want to get into the detail of the matter.

  • Thanks for reply. I dont fully agree with the code example reason. I think this one lack responsibility. This distributing alone can qualify for unsecure implementations all over the world. Far from all developers (and bloggers) do deeper analysis because of infinite number of reasons. There is simply no idea to shortcut such a parameter in a sample, which is so crucial for the functionality (functionality here is security). As if it's enough, as weaking is mentioned, the sample reminds of how Tripple-DES in NTLMv2 is constructed, so maybe mid skilled even not notice it. – Independent May 25 '16 at 13:35
  • @Independent. In the context of what Xander added about your implementation using RFC2898/PBKDF2, this may be of interest crypto.stackexchange.com/questions/26537/… – Little Code May 25 '16 at 14:55
4

The answer by Little Code is correct in that it is absolutely not safe to reuse part of the key as an IV, particularly if you intend to use the key to encrypt more than a single piece of data.

HOWEVER: That is not what the code snippet you reference in your question is doing.

Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt);  
rijndael.Key = pdb.GetBytes(32);  
rijndael.IV = pdb.GetBytes(16);

The way Rfc2898DeriveBytes.GetBytes() works, successive calls return additional bytes, not the same bytes. So calling GetBytes(32); and then GetBytes(16) is functionally equivelent to calling GetBytes(48); and then splitting the results into arrays of lengths 32 and 16.

This is a safe construction if, and only if the salt is globally unique. (Practically, this usually means random and of appropriate length.) The reason that you would get both the Key and the IV this way is because you either need to a) store the IV for decryption or b) know how to re-generate it for decryption. Since we already need to store the salt that we use as an input to Rfc2898DeriveBytes, it's easier, and makes more sense to use it to generate both the key and IV then to have to store an IV as well. Again, as long as the salt is unique, we'll end up with a secure IV that will be unique to this one password/salt combination.

  • thank you for the extra detail. Although I would still be tempted to say that if you already have a decent PRNG going to give you the strong salt, you might as well just generate the strong random yourself instead of deriving it ? – Little Code May 25 '16 at 14:52
  • @LittleCode From a security perspective there's certainly nothing wrong with that approach. The only downside is that you now have to store both the salt and IV for future decryption. Not the end of the world by any means, but makes a difference to some. – Xander May 25 '16 at 15:03
  • Thanks for the comment. It make perfect sense that the Rfc2898 derives and create a new byte array. You state that this is irreversible even if you know the original bytearray used as SALT together with password? The GetBytes(n) will produce the same set of bytearrays for each run, if you put salt as bytearray into the Rfc2898DeriveBytes-constructor. If you insert an INT, its a length spec for a bytearray to randomize and can use into the IV and Key. But in this mentioned common code sample, bytearray is used. – Independent May 27 '16 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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