11
$\begingroup$

The message format includes a datetime field in the clear. Is it okay to also use this field (or some hash thereof) as the initialization vector?

In this case, CBC is the mode being used.

$\endgroup$
  • 1
    $\begingroup$ "I'm thinking of a sha256 hash of a number between 1 and 10!!" -- you will find that answer in 10 tries. There will surely be other data around that narrows down the timestamp. If you can narrow it down to a second, then you really only have a few bits of entropy. $\endgroup$ – Rob Jul 12 '16 at 2:44
11
$\begingroup$

It depends on the chaining mode. With recent modes like EAX and GCM, the IV just needs to be non-repeating, so a timestamp is OK (as long as you take care never to issue two messages with the same timestamp: this can be a problem if you emit two messages in, say, the same millisecond, or if the sender clock is somehow reset through manual action or NTP; notably, consider that the NTP protocol is rarely protected at all, so an active attacker may play tricks on your clock).

With CBC, the IV must be uniformly random, and, depending on the situation, should be unpredictable by the attacker. For instance, if the attacker can trigger the encryption of some messages of his own choosing, he may use a predictable IV to obtain precise block encryptions which he could then use to alter some other messages in a controlled way. A timestamp is highly predictable. A tempting design would be to compute the IV with HMAC over the timestamp, using a shared secret key for that; on a general basis, use a Key Derivation Function to extend your encryption key into two keys, one for HMAC and one for the actual AES encryption (make it three keys: one for the HMAC-for-IV, one for encryption, and one for the MAC which you of course add to the message to thwart active attackers). However, making your own designs is known to be dangerous, and modes like EAX and GCM already do that job better.

To sum up: using a timestamp is a bit tricky since it is only mostly unrepeating. And it will not work well with all chaining modes.

$\endgroup$
  • $\begingroup$ @NicHartley I think your computations are a bit off; you probably forgot a square root. With a 12-byte (96-bit) IV string, and $n$ values, you will have a collision with probability $2^{-20}$ (one-in-1048576) when $n$ is such that $n^2/2 = 2^{76}$, i.e. $n = 2^{38.5}$, or about 389 billions. Taking an average sand grain diameter of 0.3 mm (that would be typical sand with medium coarseness) made of crystalline silica (2.648 kg per cubic meter), this would amount to only 14.6 kg of sand. $\endgroup$ – Thomas Pornin Jul 5 at 13:00
  • $\begingroup$ For a 50/50 probability, you'll need $n$ slightly above $2^{48}$, a larger number, but not impossibly large; it would yield about 12.4 metric tons of sand. This would fit in a medium-sized truck. $\endgroup$ – Thomas Pornin Jul 5 at 13:06
  • $\begingroup$ In fact, IV size of GCM is known to be a bit too small for comfort. If you generate random IV and rely on probabilities to avoid collisions, you will be better off with a 16-byte IV (128 bits). As per the GCM spec, this will be processed with GHASH into a 16-byte starting value for CTR (including the start value for the 32-bit counter), thereby reducing the risk of collision by some amount (depending on how many bytes you encrypt in a single message); moreover, that GHASH call uses the secret key, so random collisions will be made non-obvious to onlookers. $\endgroup$ – Thomas Pornin Jul 5 at 13:09
  • $\begingroup$ Shoot, you're right -- I misplaced a paren and divided the wrong things. My bad. $\endgroup$ – Nic Hartley Jul 5 at 14:28
2
$\begingroup$

AES does not have any IV. Modes of operation have IV. IV usually does not need to be secret, However, in most cases, it is important that an initialization vector is never reused under the same key. For CBC and CFB, reusing an IV leaks some information about the first block of plaintext, and about any common prefix shared by the two messages.
For more information see the Wikipedia article.
The ECB vs CBC Encryption Modes post is maybe useful.

$\endgroup$
2
$\begingroup$

In addition to @Thomas Pornin's excellent answer, I would point out another risk with using the date+time to generate the initialization vector: it might repeat. There are two plausible ways that it might repeat:

  • Rapid-fire messages. You don't mention the granularity of your timestamp, but let's say it is down to the millisecond. If you transmit two messages within the same millisecond (which can easily happen if some applications is sending multiple messages at maximum rate, for a little while), then those two messages will receive the same IV.

  • Time rollback. There are various circumstances under which a computer's clock can flow backwards and repeat previously seen times. Perhaps the most prominent is use of virtual machines, where taking a checkpoint, running forward, then rolling back to the checkpoint and running forward again may cause the same timestamp to be reused. In this case two messages may receive the same IV.

In either case, it is not safe to encrypt two messages under the same IV: if you do, an eavesdropper might be able to learn partial (or complete) information about the two messages that were sent under the same IV.

For this reason, I would normally not recommend using a timestamp as your IV. I think a cryptographic-strength pseudorandom 128-bit number is safest and easiest to implement correctly. A non-repeating sequence number is also sufficient for some modes (but beware of crazy ways that it can repeat, e.g., wrap-around, VM checkpoint/restore; and make sure to only use it with modes that can tolerate non-random IVs).

$\endgroup$

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.