5

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?

Carl
  • 53
  • 1
  • 4

2 Answers2

4
  • 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".

3

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.

Paŭlo Ebermann
  • 22,946
  • 7
  • 82
  • 119