In my project we would like to encrypt and authenticate the the communication channel between our server and our Arduino nodes, which relies on an underlying TCP channel.

We have chosen AES in CTR mode as the cryptographic cipher of our choice, transmitting the initialization vector and the message number in clear such that both know which to use (next).

Since encryption is not enough (and integrity actually much better), we are also pondering which authentication algorithm to use. HMAC-SHA256 or simply SHA-256 seem to be suitable candidates. We would encrypt then authenticate.

The questions are:

  • do we need to authenticate the initialization vector?
  • is SHA-256 enough for authentication purposes, or should we use HMAC-SHA-256?
  • if we use HMAC-SHA-256, should we use a different key than the one used for AES encryption?
  • is SHA256 a good choice to use for the initialization vector? We would use only 128bit of the resulting hash in case of short messages, or multiples of 128 Bit

Or should we pertain to other solutions?

  • 4
    $\begingroup$ Always authenticate the IV. A hash (such as SHA-256) offers no authentication whatsoever. Never use the same key for more than one purpose (unless you really know what you are doing). Theses are basic principles you should live by. I do not understand your last question. $\endgroup$
    – Maeher
    Apr 9 '13 at 15:31
  • 3
    $\begingroup$ Is there a specific reason you are inventing your own protocol, rather than reusing an existing one (such as TLS or SSH)? Cryptographical protocols are subtle; it's easy to make mistakes; you're better off relying on something which has already been vetted. $\endgroup$
    – poncho
    Apr 9 '13 at 15:31
  • 1
    $\begingroup$ Both encrypt-then-(H)MAC-including-IV and hash-then-encrypt provide integrity in an adversarial setup. Neither encrypt-then-append-hash nor encrypt-then-(H)MAC-except-IV provide that. $\endgroup$
    – fgrieu
    Apr 9 '13 at 16:04
  • $\begingroup$ Why/how do you want to use a hash (of what?) to produce the IV? $\endgroup$ Apr 9 '13 at 18:05
  • $\begingroup$ Since I need an IV that the Arduino can reproduce, I need a counter. Of course I can start with 128 0's, but I thought that it would be more suitable to use a hash function to derive the IV from the counter, since we are using AES in CTR mode. Also, using TLS is hard on Arduino Uno? I know of no libraries that perform fast enough. $\endgroup$
    – Carl
    Apr 9 '13 at 21:26

For counter mode, the only condition for your IV (i.e. initial counter value) is, that it doesn't repeat over messages, and more, that it doesn't collide with any of the counter values in use for all the messages using the same key.

  • One way to do this would be to simply count forward from the last message, e.g. first message uses 1, 2, 3, second message uses 4, 5, 6, 7, third message uses 8, 9, and so on.

  • Another way would be to split the counter in two parts, one for the "in-message-counter" (which would start at zero for each message) and another one for a "message-number" (which would be incremented between messages).

  • Or you can use a (pseudo)random value as the IV for each message (then the non-collision property holds with high probability as long as you don't send excessively many messages with the same key). That could be a hash of the message number, but there is no real advantage to the first two versions.

If your protocol allows for reordering or dropping of the messages (i.e. message three can arrive before message two, and then is to be processed first), like UDP, you should include the starting counter in your message (it doesn't have to be encrypted). (But then you should make sure that duplicate messages either are ignored, or don't harm when processed twice.)

If the messages always arrive in the same order as sent (for example if you are sending them over a TCP-like channel), the the receiver can calculate the next counter value by the same rule as the sender (and drop the connection when the MAC fails).

The authentication (whatever it is) should include the initialization vector (or all data from which it can be derived) (whether it is sent or implicit). There is some consensus that "MAC the ciphertext" is generally better than "MAC the plaintext", as it avoids some chosen-ciphertext attacks.

"Hash plaintext and encrypt" (what was one of the proposals) is a bad idea when used with counter mode (It also needs careful examination with other modes):

If the attacker knows (or can guess or choose) the original message, she also knows the original hash. She can then chose an own message of the same length, calculate the new hash, and XOR both new and old message and hashes into the original ciphertext to get a valid original ciphertext of the new message (with the same IV).

A proper MAC (with its own key) does avoid that problem, as does an authenticated-encryption mode of operation.

  • $\begingroup$ A MAC with the same key would also avoid that problem, I guess? But never reuse the same key, as Gilles also stated, is better. $\endgroup$
    – Carl
    Apr 11 '13 at 21:32
  • $\begingroup$ Depending on the MAC algorithm in might be okay to use the same key, or not. HMAC-SHA256 has a structure different enough to AES so the same key is likely not a problem, though it still has a bit of a bad taste. Using e.g. CBC-MAC with CBC-mode with the same key is a really bad idea. $\endgroup$ Apr 12 '13 at 7:08
  • Yes, authenticate the IV. If an attacker changes the IV while keeping the rest of the ciphertext intact, they'll change the message. Just because they can't change the message to an arbitrary value doesn't mean they can't cause harm (if nothing else, they can send random junk until they hit a valid command or a bug in your parser, or feed you invalid data).
  • SHA-256 doesn't authenticate anything whatsoever. Its use for integrity is that if a message changes, so does its SHA-256 digest, and it's easier to ensure the integrity of 256 bits than of a gigabyte-long message: a giest allows you to do integrity by proxy. But you still need to ensure the integrity of the digest somehow.
    HMAC, in contrast, incorporates a secret key, and can only be produced with the knowledge of the secret key, so it provides authenticity. Note that authenticity doesn't imply integrity: an attacker could replay an older, equally valid message.
  • I'm nowhere nearly a competent enough cryptographer to know whether using the same key for the HMAC and the encryption is a problem, but my gut reaction to “use the same key for” is don't do it. Either keep two separate keys, or if you only have 128 bits of key material, derive two 128-bit keys from these 128 bits.
  • If you never send the same message twice, then it is valid to use the first (or last) 128 bits of the SHA-256 of the message as an initial nonce (IV) for CTR mode. CTR mode absolutely requires a unique nonce per message; the nonce is commonly generated at random, which ensures unicity even if the messages are identical, but that isn't a requirement unlike some other block chaining modes.
    If you send the same message twice with the same IV, the ciphertext will be the same, and eavesdroppers can find out. The only way to remedy this is to have a source of uniqueness. Ideally, you run a cryptographic PRNG on the Arduino, making sure to seed it either with sufficient hardware entropy (I don't know what the Arduino's capabilities are) or with entropy provided securely (with both authentication and confidentiality) from some more capable machine. Another alternative is to send a unique token from the server before the Arduino sends each message, and include that in the message; the token has to be integrity-protected but doesn't need to be confidential.

Now that I've answered your questions, let me answer your question.

Don't do this. Use authenticated encryption (GCM or EAX).

authenticated encryption is "combined traditional encryption and independent MAC, done properly".

  • 2
    $\begingroup$ Or even better, don't do this use TLS/SSH. $\endgroup$
    – mikeazo
    Apr 9 '13 at 18:56
  • 2
    $\begingroup$ Gilles, thanks for your answer. For performance reasons and for the lack of a suitable library, we have to invent our own protocol. What I do not understand is: if I encrypt the SHA-256 hash of the message together with the message, then by decrypting the message I should be able to verify the integrity and also authenticate it? Not really according to the book, but still? Also, if I don't authenticate the IV, there will only be garbage that cannot be successfully checked for integrity, since the encrypted message itself contains a hash of it for checking integrity? $\endgroup$
    – Carl
    Apr 9 '13 at 21:22
  • 2
    $\begingroup$ @Carl No, authentication does not imply integrity. As I wrote in my answer: a replayed message is authentic, but if the attacker substitutes the actual message for a genuine but older message, the integrity of the communication has been broken. $\endgroup$ Apr 9 '13 at 21:33
  • 1
    $\begingroup$ @Carl In CTR: each block of the message is $M_i \oplus C_i$ where $C_i$ is calculated from the key and IV. If the attacker changes the IV, they're changing the message you get upon decoding. They can't predict what the altered plaintext will come out as, but they can still e.g. hammer your parser with fake messages until they find a bug. As for the HMAC, it authenticates the sender only as one of the possessors of the symmetric key, you can't do any better with a shared key. $\endgroup$ Apr 9 '13 at 22:05
  • 1
    $\begingroup$ @Gilles: I agree. But the plaintext I thus decrypt can't be checked successfully with the hash that is included in the encrypted message. I.e. I wouldn't even try to use the content if the message authentication fails. As for the entity authentication, I agree, except for what you stated earlier: it does not prevent replay attacks. But the HMAC data authentication, it does imply integrity. $\endgroup$
    – Carl
    Apr 9 '13 at 22:13

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.