|
Others have rightly mentioned HMAC as being a good option, but being approximately equal to the work of the CBC encryption. There are peer-reviewed standard cipher modes that provide a cryptographic checksum with a low overhead per block plus one extra block cipher operation per message. These are generally known as single-pass authenticated encryption modes. GCM mode is probably your best option. If you're willing to rekey every 64 GB, are releasing your code under an OSI-approved Open Source license, and you're okay using a mode that's patented, OCB mode is another option. Really, you don't want to use a static key. Ideally you'd either use the shared master key just to provide confidentiality (in case ECDH is broken) and authentication for ECDH session key agreement. Failing that, you'd use the shared master key and the current time to generate the session encryption keys in order to limit the amount of traffic under a given session key that an attacker can use. session_counter = (AES256_enc(master_key, 0) + time()) | 0x0FFF; session_key = AES256_enc(master_key, session_counter); will generate for you a 128-bit key that changes every 1.13 hours (2^12 seconds). If an attacker can notice some traffic pattern that gives away when the rekey happens, this will give away the lower 12 bits of AES256_enc(master_key, 0), but this is very little plain text to work with. Note that due to the | 0x0FFF, it's impossible to accidentally use the leaked bits in a session key by using AES256_enc(master, 0) as a session key. If you want a 256-bit session key, it's best to use a second 256-bit shared key to encrypt session_counter to generate the second 128-bit half of your session key. Of course, in practice you'd pre-calculate when the session_counter rolls over rather than recomputing the session key for every packet. You either live with data being lost a few seconds every hour, synchronize clocks very well using GPS or NTP, or else calculate two sets of session keys and use the MACs to figure out which key the sender is using. When using two sets of session keys, you'd throw away the "expired" key and calculate the "upcoming" key 2^11 seconds after session_counter rolls over. (That is, you actually roll your pair of session keys half out of phase of when you'd roll a single session key.) Edit: Changed to use C's xor operator for exponentiation since Python's double-asterisk notation doesn't display properly on HN. |