# CTR mode nonce with aggressive key rotation policy

I'm writing a small encryption library which will be required to use the shortest possible amount of overhead for describing ciphertexts. I want to use CTR mode with a 6-byte random nonce.

Normally I would never disregard best practices like this, but I think in this context it is acceptable because the encryption keys will be rotated frequently. As I understand it, the weakness in CTR mode occurs when the same nonce AND key are used to encrypt. If the key is rotated, say, every 2 months, it's unlikely that there would ever be a nonce collision.

This is a heterodox use of CTR mode - feel free to savage my idea if it is flawed. Thanks for your help.

-

A 6-byte nonce can expect to receive a collision 0.01% of the time after around 240,000 nonce generations (based on a birthday attack). After 100 such rotations (a little under 17 years, based on your 2-month rotation policy), that comes out to a likelihood of just under 1% of experiencing a collision. On the surface, to me that seems like a reasonable margin of security.

If practical, you may also want to consider simply using an autoincrementing counter for your IV. Allow the first byte to be a machine identifier, and then use a mutex to synchronize access to the remaining five bytes. Whenever you need an IV, lock the mutex, read the current value as the IV, increment it by one, save it, and release the mutex. This allows you to encrypt over one trillion messages with a single key before the nonce rolls over, and has zero possibility of collision as long as you detect IV wraparound.

-
Just saw your edit - nevermind – pg1989 Jul 19 '13 at 23:40
How do you get from 0.1% and 100 such rotations to 1% ? $\:$ – Ricky Demer Jul 20 '13 at 0:19
Via tpyo in my math. Updated. – Stephen Touset Jul 20 '13 at 1:16
The counters in your last paragraph should be initialized to random values, so that the $\hspace{1 in}$ system is still probably safe even if the same first byte is used on more than one machine. $\hspace{.9 in}$ – Ricky Demer Jul 20 '13 at 2:57
Do you mean the second byte, or the entire remaining five bytes? There being a large, incrementing counter is what guarantees there can be no collisions until the counter wraps around. – Stephen Touset Jul 20 '13 at 3:51

The "shortest possible amount of overhead for describing ciphertexts" is achieved by

encrypt(key,nonce,plaintext) =
prefixfree(length(nonce)) ||
FPE ( length(nonce)+length(plaintext) , PRF(key,length(nonce)+length(plaintext)) , nonce || plaintext)

The basic idea is to use independently keyed block ciphers for each possible plaintext length, and include the nonce in what the block ciphers are evaluated on. Since one can't quite independently key the block ciphers, one keys them with the output of a pseudo-random function (such as HMAC) evaluated at their block size. The simple way to include the nonce in what the block ciphers are evaluated on is to concatenate the nonce with the plaintext, so that is done. Finally, to allow the keyholders to extract the plaintext, one puts a prefix-free encoding of the nonce's length at the beginning of the ciphertext.

If you would be using fixed-length nonces, or more generally, if keyholders can efficiently determine length(nonce) from length(nonce)+length(plaintext), then you can skip the prefixfree(length(nonce)) part, since length(nonce)+length(plaintext) would be the length of the ciphertext.

These ciphertexts will always reveal length(plaintext). Unless you skip the first part, these ciphertexts will reveal length(nonce). If a nonce is reused with the same plaintext (and key), then that will be obvious because the ciphertexts will be equal. However, other than the previous two sentences, someone who does not have the key won't know whether or not a nonce was reused.

There another important point. Neither yours nor Stephen's nor my suggestion provide authenticity. (Doing so would require longer ciphertexts.)

-
I'm confused... can you reformat your post to make it a little more readable? – pg1989 Jul 20 '13 at 1:08
Reusing a nonce for plaintexts with the same length, as you say, reveals whether or not the plaintexts were equal. But this removes the cryptosystem's semantic security, which may be important. – Stephen Touset Jul 20 '13 at 1:20