[Cryptography] Question re: Initialization Vector for AES Counter Mode…

Jon Callas jon at callas.org
Wed Apr 26 18:28:47 EDT 2017


Personally, I would recommend that you *not* use counter mode or anything resembling it for writing files. There's nothing wrong with CBC mode for your purposes. (Or CFB, for that matter, but I really don't want to digress down that path.)

Counter mode creates a stream cipher. Stream ciphers nearly universally work by creating a stream of random bits (typically called the key stream) that is then XORed on to your plaintext. The first major issue with stream ciphers is that if you reuse a key, you give the attacker a trivial attack on your system. If there is any known plaintext in the first stream, you XOR that known plaintext onto the first ciphertext which yields you the key stream, and then you XOR the known key stream onto the second cipher text yielding its plaintext. In short, a stream cipher is an approximation of a one-time pad and the first rule of one-time pads is that you better use them at most one time. Put another way, when you use counter mode, you must not only keep the key secret, you must keep the key stream secret.

In a communications protocol, this typically isn't a big deal because you're going to pull a key from your random number generator, and if that isn't different, you have bigger problems.

However, when it comes to files, there's going to be the temptation to allow a seek operation. If they seek backwards, then it all starts to unravel. Worse, counter mode makes it easy to seek backwards, and thus increases the chance that someone will. If you seek, you're rewriting in place. If you rewrite in place, then you are reusing your key.  Thus, my advice is not to use counter mode for storage. Even if you do it right, it's like leaving a rake in the yard with the tines up. It's just asking for someone to come along and step on it.

Hence, just use CBC mode. Yeah, I know it sucks. Most of the ways that it sucks either don't matter when you're writing a file (because those problems come from using CBC in an online protocol, where you *should* use a stream cipher) or you can code around them (like using ciphertext stealing instead of padding). But CBC has the added advantage that it's a pain in the butt to seek in a file

But that isn't the question you asked, is it?

When you're using counter mode, it doesn't matter what the counter is. The basic construction is that you encrypt 0 and xor that onto plaintext. Then encrypt 1, then 2, and so on. It is, after all, *counter* mode. It doesn't matter at all what you start the counter with. It doesn't even really matter what you increment with. It only matters that you don't repeat a counter value. (And actually it only matters that no one knows you repeated a counter value, but don't tell anyone I said that.)

In fact, one of the really cool things about counter mode is that it doesn't matter what you start the counter with. This is unlike an IV for CBC, CFB, etc. where it *does* matter. Zero is a great counter. It's an awful IV. Counters aren't IVs, even when you pass them into the "iv" parameter in the api.

Since you're probably going to counter mode anyway, you might want to use an AEAD (Authenticated Encryption with Additional Data) mode. I caution against using GCM mode. It has a number of things going for it: it's fast (except when it is slow), and parallelizable. It is, however, brittle. It was originally created for Chuck Jones to use in the famous Road Runner cartoon, "Beep-Beep Blockchain" with Wile E. Coyote using in his famous attempt to take over the Road Runner's mining operation. As he often ended up doing with nitroglycerin, the Coyote disrespected a nonce, and even people who haven't seen the cartoon can guess what happened in the final scene. Either CCM mode or ChaCha20-Poly1305 are reasonable alternatives. OCB might be an option for you, too, but all of that's a different discussion.

	Jon



More information about the cryptography mailing list