views:

293

answers:

5

Is there any secure way of deriving the value of IV for use in CBC mode (e.g. 3DES CBC) aside from randomizing the IV?

A: 

If you want to make them unpredictable (to anyone else) but ensure they won't repeat, you could just encrypt a one-block counter with a random key (generated once for each message key) to generate the IV. Make sure you keep the counter in persistent storage.

caf
A: 

Anything that never repeats and have no structure will work (I don't see why unpredictableness should be important - as long as the messages are also authenticated (which they ought to be)).

If you know that you will never send more than one message per second, you could use the unixtime (hash it and use the first bytes).

If you might be running in multiple threads/processes/machines, you might need to include a threadid/processid/machineid.

If you have access to generating a GUID, hashing this and using the first 8 bytes might also be a good option.

Rasmus Faber
You imply it, but should explicitly state that the IV also needs to be unique. Reusing an IV is a recipe for disaster.
Nick Johnson
Isn't "never repeats" the same as "needs to be unique"?
Rasmus Faber
A monotonic counter never repeats, but if I'm using it on multiple instances, it's not unique.
Nick Johnson
+1  A: 

NIST's special publication 800-38a discusses methods for the generation of IVs in Appendix C. One method that is proposed there is to use a counter or nonce, encrypt it and use the result as an IV. Contrary to e.g. the CTR mode it is necessary that a potential adversary can not predict the IV.

There exist attacks if predictable IVs are used. See for example this paper. (I'll try to find a more accessible version).

Accipitridae
A: 

You may wish to look at counter mode, rather than CBC. Counter mode allows random access to encrypted data and can be parallelized.

vy32
+3  A: 

It's often stated that you need to guarantee that you never re-use an IV value. However, I find that this often confuses newbies. The rule of thumb is:

Always guarantee that the key+IV combination is unique.

The important corollary is:

If you generate a new key every time, you don't need an IV.

So, if you are re-generating the encryption key randomly every time, you do not need to worry about the IV at all -- you can use a zero IV and it will not reduce the security of your protocol.

Also, if you use a reliable transport such as TCP, you can use a single IV/key for the whole connection lifetime. Because TCP guarantees lossless and in-sequence delivery, there is no need to re-generate an IV for every single message.


But this is not always possible. As other people posted, for per-session keys, keeping a counter in RAM and incrementing it for each sent message is a good idea.

However, for long-term keys, putting it on persistent storage is often problematic, because users may copy your program files, or the computer might lose power when your counter hasn't been flushed to disk yet -- and you will be using the same IV again. It's much easier if you don't have to worry about this. For these purposes, I'd suggest generating the IV randomly (e.g. /dev/urandom on Unix) or using nanosecond or microsecond-precision time (e.g. gettimeofday() on Unix).

intgr