9
$\begingroup$

I'm working with a server/client system that has securely negotiated a private key. I need to encrypt/decrypt messages passing in both directions which are typically between 100 bytes to 100 KB. I'm working with AES-128 bit, but I cannot really understand how the private key is to be used with the encryption algorithm.

"You should ALWAYS use unique IV's every time you encrypt, and they should be random. "

Based on the previous point, how can I calculate a 'unique' IV on the server and client, when all I have is the secure Key on both sides? Or is it fine to calculate a random IV and send the IV on the wire? Wouldn't this open up a security hole?

  • Data: Small sized messages, often with repeating data.
  • Key: I've got a secure key on both sides.
  • IV: No idea how to calculate this. Key-derivation? Salted hash? PRNG?
$\endgroup$
1
  • $\begingroup$ sidenote: Consider using some authentication(for example MAC or AES-GCM), so you can be sure the message wasn't altered by an attacker. $\endgroup$ Mar 23, 2012 at 15:29

2 Answers 2

17
$\begingroup$

Well, to start off with, IVs have different security properties than keys. With keys (as you are well aware), you need to hide them from anyone in the middle; if someone did learn your keys, then he could read all your traffic.

IVs are not like this; instead, we don't mind if someone in the middle learns what the IV is; as long as he doesn't know the key, he still can't do anything with the encrypted traffic. Because of this, one common practice is to have the encryptor select the IV, and then include it along in the encrypted message (generally immediately before the ciphertext). This eliminates half your problem (how does the decryptor know which IV to use; he gets it out of the message); the attacker can see the IV as well, but (as above) we don't care about that.

So, the question comes down to "how does the encryptor select the IV"? Well, the answer to depend comes down somewhat as to the mode you're using; the requirements for IVs differ depending on whether you're using CBC or CTR mode.

  • For CBC mode, the statement you list is mostly accurate (although I would write it as "You SHOULD use unique IV's everytime you encrypt, and they MUST be unpredictable"; there are known attacks against predictable IVs; I don't know if they apply to your scenario, but it's generally safer if we don't have to worry about them at all). There are several ways do to this; a cryptographically secure PRNG (with good seeding) works. Another thing that I've seen is you take a counter (say 0 for the first message, 1 for the second, etc), encrypt that (in ECB mode) with the same key you'll be encrypting the message in, and use that ciphertext as the IV. This works because the ECB encryption of a counter is unpredictable to anyone who doesn't know the key. Of course, if both ends of a bidirectional channel use this method, they need to either use different keys or make sure that their counter values won't overlap (e.g. one end could use only even values and the other only odd ones).

  • For CTR mode, the statement is less accurate; it would be more properly "You MUST always use unique IV's every time you encrypt; predictability is not a concern". Because of this, it is common to use a counter as the IV; we get uniqueness (counters obviously never repeat within the lifetime of the key), and while it is predictable, we don't care about that here. Now, there is one note: the uniqueness requirement doesn't just apply to the IV's, it also applies to the values you present to the block cipher. Because of this, one common approach for CTR mode is to take the 16 byte AES plaintext block, and divide that up into (say) a 12 byte IV field and a 4 byte message index field; during the encryption of a single message, the IV field is always the IV value we are using to encrypt/decrypt the message, and the message index field increments for every block we encrypt; say, 0 for the first block, 1 for the second, etc.

Lastly, while you haven't specifically asked about this, I believe a heads-up is required; usually, when we encrypt a message, we generally need to use an integrity check as well (to make sure that the message received was the message sent); even if you don't particularly care about message integrity, there are several clever ways for an attacker to find things about about the encryption by modifying the cipher text, and seeing how the receiver reacts. The short answer is that you should include some integrity transform (be it HMAC, CMAC, or replace the entire encryption operation with a primitive that does both privacy and integrity, say, GCM or OCB). However, to fully discuss this requires more space than I should take up in the answer to a different question.

$\endgroup$
1
  • $\begingroup$ Fantastic information! Thank you very, very much!! $\endgroup$ Mar 23, 2012 at 15:56
3
$\begingroup$

I assume you're using CBC mode.

Or is it fine to calculate a random IV and send the IV on the wire?

That's perfectly fine. It's standard practice to send the IV over the wire together with the message. IVs aren't secret. Typically they're used so encrypting the same text twice gives different output.

$\endgroup$

Your Answer

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

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