I'm writing a TLS 1.2 implementation (in C#) using a custom protocol.

My question is how to generate the IV attached to each message, I don't want to use RandonNumberGenerator because I've heard it is slow. Instead, I would like to use some PRNG. I'm only going to suppport AES128/256.

From reading around I understand that using a random IV and encrypting a counter (should start at a random number) and use that as the IV is OK. Is that true? After how many uses should I use a new random IV? Can I use the same key for generating the IV and encrypting the message?

Is using .Net's Random class with a seed from RNGCryptoServiceProvider can do the work? After how many uses should I use a new seed?

  • 1
    $\begingroup$ Welcome to Cryptography Stack Exchange. Did you measure that RandomNumberGenerator is too slow? Which mode of operation do you use? (They have different needs for an initialization vector.) $\endgroup$ – Paŭlo Ebermann May 15 '13 at 8:36
  • 1
    $\begingroup$ If you need random numbers for cryptographic purposes, most likely a non-crypto Random class will not give good results. $\endgroup$ – Paŭlo Ebermann May 15 '13 at 8:37
  • $\begingroup$ I'm using cbc, i didn't check performance of RandomNumberGenerator but I have read that strong number generator can become slow under high frequency. $\endgroup$ – somdoron May 15 '13 at 12:01
  • $\begingroup$ RNGCryptoServiceProvider isn't that slow. It just has a large per-call overhead, so you need to ask for a few kilobytes in a single call. On my notebook it can generate around 4 million IVs (with 16 bytes each) per second on a single core. $\endgroup$ – CodesInChaos May 15 '13 at 21:30
  • $\begingroup$ I'd be curious to see your C# implementation. Do share a link if you can. $\endgroup$ – goodguys_activate May 18 '13 at 15:03

To answer your specific questions:

From reading around I understand that ... encrypting a counter and use that as the IV is OK, is that true?

For CBC mode, that is absolutely true, as long as the key that you use to encrypt the counter is secret (that is, not known to any possible adversary).

Should I start in random number?

Actually, that's a matter of taste; you could start with 0 if you wished.

If you use a known counter, the attacker would learn the encryption of (for example) [0], [1], [2], etc. This isn't much of a problem with CBC mode; whenever you encrypt known plaintext, the attacker gets several more known plaintext/ciphertext pairs. This helps the attacker only if in the future, the CBC mode happens to use the exact same plaintext (to generate the exact same ciphertext), with AES, you have $2^{128}$ possible plaintext/ciphertext pairs; accidentally reusing one is improbable (and so adding a few more because you encrypt a few known counters isn't going to be harmful.

Now, if it's convenient to start at a random number, well, that doesn't hurt anything. However, I wouldn't do it unless it was easy.

After how many uses should I use a new random IV?

There's no requirement to ever reseed your counter. You'd run into problems if you encrypt more than $2^{64}$ messages or so; however CBC mode will already run into problems in that case (and you wouldn't be able to encrypt that many messages in a reasonable amount of time anyways).

Can I use the same key for generating the IV and encrypting the message?

Not only can you, you're better off if you use the same key. Remember where I said the key you encrypt the counter should be "not known to any possible adversary"? Well, we already have such a key; the key you use to encrypt the message. After all, if an adversary does have that key, he can read the message already; any weakness stemming from the IV being predictable is irrelevant. Hence, by using the same key to do both, we reduce the number of secrets we need to keep from an adversary.

One small caveat: if you reuse the key in this way, the attacker shouldn't be allowed to choose or control the counter. It would be fine to use a counter that starts at 0, or a counter with a random starting point (where the starting point is generated using RandomNumberGenerator) as you suggested.

| improve this answer | |
  • $\begingroup$ Thanks. To sum it up, on the encryptor side I'm using the symmetric key with strong Random IV. The first block I encrypt of every message is the counter (+padding) and then the rest of the message, on the decryptor side I'm taking the first block as an IV and then decrypt the rest of the message? $\endgroup$ – somdoron May 15 '13 at 15:40
  • $\begingroup$ @user1966074: The decryptor side does the standard CBC-mode decryption, which is (for TLS) precisely as you stated. $\endgroup$ – poncho May 15 '13 at 18:02
  • 1
    $\begingroup$ How do you know that it's safe to re-use the same key for encrypting the IV and for CBC encryption? That smells fishy to me. (For instance, in a chosen-nonce chosen-message attack scenario, this smells like it might allow distinguishing attacks.) Superficially, re-using the same key in this way seems like dangerous practice, unless there's a proof of security to demonstrate that nothing can go wrong. Do you know of a proof of security for this construction? $\endgroup$ – D.W. May 16 '13 at 5:21
  • 1
    $\begingroup$ @D.W.: why, yes, I do have a proof of security: see eprint.iacr.org/2008/121.pdf ; see the part where they show an encrypted counter for a CBC mode IV is secure $\endgroup$ – poncho May 16 '13 at 13:27
  • 1
    $\begingroup$ @poncho, OK, thanks. It looks like if you encrypt a (generalized) counter, CBC mode is OK -- but here it's critical that it's a counter that the attacker has no control over. If you allow the attacker any control over the counter-like-thing you're encrypting, then that proof doesn't apply, and I suspect attacks become possible. $\endgroup$ – D.W. May 16 '13 at 18:05

Have you considered generating the IV in a cryptographically pseudorandom way? This approach makes it easiest to be sure that you're not introducing some subtle weakness in your IV selection.

I would start by benchmarking how fast it is to use RandomNumberGenerator. If that's fast enough, job done. I would not give up on that idea until you know that it is too slow.

Another way to generate IVs in a cryptographically pseudorandom way is to build a new cryptographic PRNG for generating IVs. Each time you need a new IV, you request some pseudorandom bits from the PRNG and use them as the IV. Here's one way to build such a cryptographic PRNG yourself:

  • At initialization time, generate a fresh new 128-bit seed using a RandomNumberGenerator. We'll build a cryptographic PRNG that generates as much pseudorandom output as desired, derived from this seed, using AES CTR mode.

  • The seed to the PRNG is a 128-bit AES key k (generated randomly using RandomNumberGenerator). The state of the PRNG includes the key and a counter i.

  • When the client requests a new pseudorandom value, you increment i, encrypt i using AES under key k (in ECB mode), and then output the resulting 128-bit ciphertext. Notice that the seed k should not be re-used for any other purpose; it should be generated randomly using RandomNumberGenerator and then used only in this PRNG.

| improve this answer | |

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.