5

I'm looking at some code, and in a particular scenario, the code would need to generate two IVs.

The second IV-generating code simply uses the C# Rijndael GenerateIV()

The first IV-generating code though takes part of the MAC address and part of the current time and inserts pieces of these data into a 16-byte array.

In both pieces of code then, the generated IV is then processed a constant X amount of times by getting the hash of the IV, and then getting some random bytes and re-hashing.

Questions:

  • Do you see any advantages in having two ways of generating the IV?
  • Is the post-IV generating hashing necessary or overkill? - and is it something standardized or some obscure idea?
  • Could there be any scenarios or configurations in which the GenerateIV function not provide random data?

Notes:

  • These IVs are intended to be used in encryption
  • CipherMode is CBC
3

The right way to generate an IV for CBC mode is with a cryptographically secure random generator. There are cases where a non-random IV is ok, but unless you've carefully analyzed your system to be sure that you fall into these cases, you should go with a random IV. There are very few situations where using a non-random IV would have any benefit anyway, so go with a random IV.

I'm not familiar with the C# API, but given that the documentation of GenerateIV states that it “generates a random initialization vector (IV) to use for the algorithm”, it appears to be a valid way to generate an IV for CBC (but CreateEncryptor does the same job already).

Taking the hash of these random bytes is strictly speaking a risk, because it reduces the entropy of the IV: cryptographic hashes are not known to be surjective. (I assume you mean a cryptographic hash such as SHA-256; a non-cryptographic hash would definitely be problematic.) However, I don't think there is any concrete problem with that: in practice, I think it's harmless.

Appending some random bytes and hashing repeatedly again should be equally safe. However, it's needless complexity. Needless complexity should raise alarm bells in any security context. This increases the risk of an implementation bug, such as leaking confidential data (not a big concern here though, as the IV doesn't need to be confidential, but it would be a definite consideration if you were generating a key), overwriting data due to a buffer overflow or incorrect pointer calculation, getting the iteration count to 0 when at least one iteration is necessary, etc.

The second method you propose is definitely not safe without the extra hashing-with-random step. MAC addresses and time are predictable, and CBC requires an unpredictable IV. The attacks against CBC with a predictable IV don't apply to all systems (they rely on the adversary being able to submit messages for encryption), but why take a risk? In addition, MAC addresses and time are not necessarily unique: think cloned virtual machines, multithreaded programs, fast process that serves two clients in the same clock tick, etc.

With the extra hashing-with-random step, starting from the MAC address and time should be indistinguishable from random, provided that enough random data is injected. But we're back to the complexity problem: how sure are you that you're getting it right?

If the reason for this extra complexity is “to make it more random”… random doesn't work that way. You can't make random more random just by messing with it, there's a serious risk that you'll mess it up and make it less random.

Doing anything other than taking a random IV (e.g. with GenerateIV) increases maintenance cost (starting with the time you're spending now worrying about it), reduces performance, and increases risk. So just use a random IV.

If deploying an updated version of the code is expensive, this isn't a critical problem. (If the IV was just MAC+time, it may or may not be critical depending on the overall system.) But it should be fixed in the code base and deployed with the next normal release.

  • This is very detailed, thanks! Do you think there may be some scenarios or machine configurations in which GenerateIV alone does not suffice in providing random data? - which would answer why the original author did the extra steps. – Zuiq Pazu Nov 9 '15 at 14:08
  • @ZuiqPazu I don't know of any scenario where GenerateIV alone would not be the right choice. There may be some weirdness of the .NET API that I'm not aware of — I have zero experience of Windows programming (I'm an embedded and Unix guy). But the most plausible reason in my experience is that the original developer doesn't understand randomness and added some voodoo to make it look more random, mistakenly assuming that more complex implies more random. – Gilles 'SO- stop being evil' Nov 9 '15 at 14:26
3

A secure pseudo-random number generator (CSPRNG) is about as secure as you are going to get. Both of the references you point to are CSPRNGs so either should be sufficient for an IV. Hashing doesn't make random more random. Using two different mechanisms makes no sense and doubles the chance of making a mistake.

In the case of GenerateIV, things are already random so the subsequent hashing and addition of more random data doesn't help.

The use of the MAC address and time to create the initial array seems rather pointless as both of them are far from secret. If the computer's MAC address is known to an attacker and the time, they can quickly guess the exact time stamp. So all of the randomness from this IV creation comes from the from the random bytes added at the end. Perhaps that is sufficient, I can't tell without seeing the actual code.

Note that, according to Kercckhoff's principle, there is no added benefit obtained by using a secret algorithm.

My advice is to simply use the data from GenerateIV as your IV and to do this in all cases.

  • Thank you for the answer. Do you think there may be some scenarios or machine configurations in which GenerateIV alone does not suffice in providing random data? - which would answer why the original author did the extra steps. – Zuiq Pazu Nov 9 '15 at 14:07
  • As GenerateIV is stated to be a secure random function, only a vu6in it would make it not sufficient. I know of no such vulnerability, but one may have existed. Odds are that if there was such a vulnerability, all secure RNGs on the platform would have been broken. Perhaps it was written at two different times so used two different strategies? – Neil Smithline Nov 9 '15 at 15:52

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.