1
$\begingroup$

I'm writing a symmetric encryption scheme for a product that I'm working on which doesn't store sensitive data (license validation data). I'd still rather do it right and reuse it than do it wrong and make something useless.

I have some concerns about HMAC after encrypting and making sure that the HMAC actually serves its purpose. I read this article on avoiding mcrypt vs OpenSSL which pretty adamently promotes the concept of MAC-after-encryption.

Now here is my current process for encrypting the data (you can imagine how the decryption side works):

//PHP7
function encrypt($message, $key){
  $method = 'aes-256-cbc';

  if (mb_strlen($key, '8bit') !== 32) {
    throw new Exception("Needs a 256-bit key");
  }

  $ivsize = openssl_cipher_iv_length($method);
  $iv = random_bytes($ivsize);

  $ciphertext = openssl_encrypt(
    $message,
    $method,
    $key,
    OPENSSL_RAW_DATA,
    $iv
  );

  $hmac = hash_hmac('sha256', $iv . $ciphertext, $iv, true);

  return base64_encode($hmac . $iv . $ciphertext);
}

My concern is that the HMAC key is the same as the IV which is prepended to the data stream. In theory, anybody attempting to break this can figure out that the first 32 bytes are the HMAC, the second 16 bytes are the IV, and the rest is the cipher text, since it seems to be an industry standard. Somebody running a Vaudenay Attack could potentially modify the cipher text and regenerate the HMAC easily using the IV.

So would it be more secure to use the AES key for the HMAC since that is not passed or stored? Or maybe something different like the XOR of the AES key and the IV? Or a completely new key using another round of random_bytes()?

Should the MAC key be treated just like the AES key in terms of secrecy?

This post titled "Why Can't I use the same key for encryption and MAC" suggests that it is not appropriate to do for AES-CBC mode, lets assume that AES-CBC-MAC is not available to me (because the decryption side is a different library and language).

$\endgroup$
  • 1
    $\begingroup$ Can you not use any of the authenticated encryption protocols available (e.g. AES-GCM, or AES-EAX) that already provide the authentication/MAC for you? It will be less likely that an implementation mistake ruins the whole system. $\endgroup$ – Adrian Sep 2 '16 at 8:42
  • $\begingroup$ Why don't you just sign the data? $\endgroup$ – aventurin Sep 4 '16 at 18:10
3
$\begingroup$

Sending the MAC key with the message pretty much negates the point of a MAC, since anyone can modify the message and regenerate a new MAC using the key. Nothing theoretical with that. You might as well omit the MAC entirely.(1)

So yes, the MAC key should be considered a secret, just like the encryption key.

I think the answer in the question you linked pretty much answers the rest of your questions: Yes, you should use independent keys for the encryption and the MAC, because otherwise you run the risk of subtle interactions between the algorithms foiling your scheme. Though in the case of AES and HMAC-SHA256 you'll likely get away with it, but it would still be good hygiene to use distinct keys. Run your master key through a KDF (or just a strong hash like SHA-512) to get separate keys for the encryption and the MAC.

Of course you could generate the MAC key from random bytes given by your system's RNG, but you'd still need to transfer the key to the other end. That would need to be done similarly to how the encryption key is transmitted, not at the per-message logic which you've shown.

(1) Though an unkeyed hash would still serve to detect accidental corruption.

$\endgroup$

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.