I understand that an IV (initialisation vector) should be both unique and unpredictable, but I have found little guidance as to which is most important.
For an AES cipher I have a block size of 128 bits to use. I was considering the following scheme:
Bits 0 to 39 : Least significant 40 bits of milliseconds since epoch. This repeats approximately once every 34 years. A time frame that probably exceeds the time for which current ciphers will be considered secure, and therefore unique within the life span of the encrypted data.
Bits 40 to 63 : A 24 bit counter starting at a random value and incremented for every IV. In order to guarantee uniqueness only one thread of execution can access the counter at a time, and hence the maximum number of accesses per millisecond is limited by the clock speed of a single CPU. This application will be used on normal CPUs where clock speeds are currently plateaued well below the 16GHz speed it would take to exhaust this counter within 1 millisecond.
Bits 64 to 95 : I have concatenated information about the hardware and process and then used a SHA-256 upon this data. I am using the first 32 bits of the resulting hash as a way of uniquely identifying the source process. This reduces the possibility that 2 processes on different servers could generate the same IV. The birthday paradox suggests that if I have 65000 simultaneous processes, there a 0.5 probability of two of them sharing the same 32 bits here, but with my envisaged maximum of 1000 processes, the probability is less than 0.00001.
Bits 96 to 127 : 32 random bits drawn from a secure random number generator.
This IV would be transmitted alongside the cipher text.
My first question: is this scheme reasonable for use with the block cipher modes: CBC, PCBC, CFB, OFB and CTR?
My second question: is there any advantage to passing the 128 bits through MD5 before using them? This would be to "improve" the IV by interweaving the fixed and variable parts of the input.
My third question: alas I also have to support 64 bit block ciphers such as DES, DESede and Blowfish. I don't believe any users actually use such ciphers, but they have to be supported. Such ciphers require a mere 64 bit IV. I see nothing from the above that I can reasonably remove whilst still providing reasonable guarantees of non-repeatability and non-predictability. What can one do? All I can think of doing is taking the first 64 bits of a secure hash. Does that suffice?
My fourth question: For CBC, PCBC and CFB only, if I use the first 64 bits as a true IV, and then feed the second 64 bits into the cipher as if they were the first block of the message but discarding the output - does that work as well as using a 128 bit IV even though the cipher's block size is only 64 bits?
As a further point, the initial 32 bits of the plain text of some tens of messages could reasonably be known to an attacker. They would not be able to control the IVs generated for those messages but could identify them by other means from within some tens of thousands of messages. The prime requirement of this cipher system is to prevent an attack with such information from accessing any part of the plain text of any other message. If either the IV scheme or the cipher block modes I've mentioned would be weak in such circumstance, I would be grateful if people could point it out.
/dev/random
or equivalent for hardware-based random number generators?/dev/urandom
, not from/dev/random
.