3
$\begingroup$

Most cryptographic libraries I've encountered uses some variant of processPlaintext(...) and then doFinal() to produce the ciphertext and resets the state.

In the context of packet communications, it feels like it would be optimal to setup key and IV once and then use that single initialisation in some way for all packets on the same channel.

In the case of CBC + padding, one could re-initialise the cipher with the last cipher block as IV.

(If I use a stream cipher, or manually implement CTR, it's straightforward of course.)

It would be nice to be able to use GCM to avoid manually adding authentication. However, it would appear that the usual implementations are geared towards encrypting a single packet - and resets all internal state on doFinal.

I would like to provide only a single IV for GCM, and then in some safe way either keeping the original state, or derive consequent IVs from the initial IV in a secure manner.

What I wonder is consequently:

Are there implementations that allow you not to reset the state when finalising a packet (i.e. making encryption and authentication dependent on the previous packet)? Failing that, what would be a safe way to derive consequent IVs from an initial IV value?

(I've not read about GCM sufficiently in depth - so I have no idea if there is a significant cost to setting up GCM with an IV)

$\endgroup$

1 Answer 1

6
$\begingroup$

In the context of packet communications, it feels like it would be optimal to setup key and IV once and then use that single initialisation in some way for all packets on the same channel.

It might be optimal for efficiency standpoint, but we also care about security; it isn't necessary very good for security. You mentioned that, with CBC mode, you can use the last cipherblock as the next IV; well, you could, but there are known weaknesses with that involving chosen plaintext. Other modes don't share this specific weakness.

As for GCM, well, it was designed to be used in a very specific manner (and proven to be safe in that manner). However, if you use it in a different manner (such as reusing the same GCM state to both output an authenticate tag for one message, and continue to encrypt with another) would be, at best, playing with fire.

Now, to answer the questions you asked:

Are there implementations that allow you not to reset the state when finalising a packet (i.e. making encryption and authentication dependent on the previous packet)?

I should hope not. Using the same nonce with two different messages is known to be VERY BAD, and the obvious way to do it with continuing to use the current GCM state would appear to fall into that weakness.

Failing that, what would be a safe way to derive consequent IVs from an initial IV value?

This one is easy: the only requirement that GCM has for IVs (nonces in GCM terminology) is that you can't use the same one twice; you can use any method of generating them that abides with this requirement.

Hence, one easy way to generate IVs is to generate them sequentially, as in: $$IV_{next} := IV_{previous} + 1$$

Oh, and you did mention that:

I have no idea if there is a significant cost to setting up GCM with an IV

Assuming you use a 96 bit IV (which is the cheap size for GCM), the total cost is "one AES block encryption" operation.

Hence, selecting a new IV for each packet is both moderately cheap, and safe.

And, on a side topic: you mention that you were intending this for use with "packet communication". Well, normally with this level of communication, you need to be able to deal with packet drops; that is, if the sender transmits a packet, but the receiver doesn't receive it correctly (or at all). Because of this, I suspect you'll want to design you system so that the receiver can process packet 5, even if has never received packet 4. Among other things, this implies that you might not be able to use implicit IVs; you may need to send them explicitly in the encrypted packet.

$\endgroup$
8
  • $\begingroup$ Sorry, I meant packet as in a "packet constructed from a [TCP/IP] stream using some delimiting scheme", so there are no "packet drops". $\endgroup$
    – Nuoji
    Commented Jul 20, 2013 at 18:24
  • $\begingroup$ Under the requirement that each key is randomly generated during handshake, it should then be quite ok to start the IV at 0 and increase it from there? (Not that it is necessary) $\endgroup$
    – Nuoji
    Commented Jul 20, 2013 at 18:25
  • $\begingroup$ A quick benchmark of Bouncy Castle's implementation shows that setting up a new IV takes more than ten times the cost of encrypting a short message. :( $\endgroup$
    – Nuoji
    Commented Jul 20, 2013 at 18:45
  • $\begingroup$ @Nuoji: starting the IV at 0, and incrementing it for each encrypted message is fine; it meets the criteria that "no IV is used more than once" $\endgroup$
    – poncho
    Commented Jul 20, 2013 at 19:08
  • 2
    $\begingroup$ @Nuoji - Bouncy Castle allows you to re-init the IV/nonce in all of the standard (CBC, CTR etc.) and AEAD (GCM, EAX etc.) modes without changing the key by specifying a null KeyParameter. e.g. cipher.init(new ParametersWithIV(null, ivBytes)) changes the IV, but leaves the key-dependent state alone. You can do the same thing through the JCE API by using RepeatedSecretKeySpec as the Key in Cipher.init(). The major cost in the Bouncy Castle GCM init is key based (GCM multiplier init and (e.g.) AES init) so doing this will avoid a lot of the cost of rotating the nonce. $\endgroup$
    – archie
    Commented Jul 23, 2013 at 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.