0
$\begingroup$

I'm writing code to provide an AEAD utility. It uses AES-256-CBC for encryption and SHA-512(key+data) truncated to 256 bits as the MAC.

encrypt(
    aes_key: byte[32],
    mac_key: byte[32],
    plain_text: byte[],
    aad: byte[],
) {
    iv = crypto_random_bytes(16)
    cipher_text = aes_256_cbc(aes_key, iv, plain_text)
    aad_encoded_length = int_to_little_endian_4_bytes(aad.length);
    auth_state = sha_512(key + aad + iv + cipher_text + aad_encoded_length)
    auth_tag = truncate_bytes(auth_state, 32)
    return cipher_text + auth_tag
}

I'm primarily interested in how to order the data I'm passing to sha_512. I based it off of this: https://www.ietf.org/archive/id/draft-mcgrew-aead-aes-cbc-hmac-sha2-05.txt

Is that the best ordering?

(P.S. Though not really part of this question, my decision to use AES-256-CBC and truncated SHA-512 was based on library availability, performance, and resistance to accidental nonce reuse.)

$\endgroup$
7
  • 1
    $\begingroup$ According to the spec you cited, you should be using HMAC-SHA512, not a truncated SHA512 construct that you use. Why don’t you? $\endgroup$ Jan 12, 2019 at 1:47
  • $\begingroup$ I'm not trying to follow that particular spec exactly. I was just wondering if there's something to learn from how that spec orders the inputs to the MAC. (I'm not 100% set on using truncated SHA-512 yet, but it is faster than HMAC-SHA-512 for short inputs.) $\endgroup$ Jan 14, 2019 at 9:34
  • $\begingroup$ But it’s not secure. That should be a concern. $\endgroup$ Jan 15, 2019 at 5:55
  • $\begingroup$ That would definitely be a concern! Why is it not secure? (I was under the impression that truncated SHA-512 could be used as a MAC: crypto.stackexchange.com/q/59997/58123) $\endgroup$ Jan 15, 2019 at 6:57
  • $\begingroup$ Yes, in the fixed key length scenario, it's probably OK. But just optimise the HMAC so that it's just one hash call. I'd have the aad-encoded length before the aad, as a general principle (might be easier to parse), but there's no real problem with adding it at the end, I think. In your function you don't return the length of the cipher text? $\endgroup$ Jan 15, 2019 at 7:05

1 Answer 1

2
$\begingroup$

This part of the standard (at the end) explains why the length of the authenticated data is at the end, namely to ensure a unique input to the MAC for all pair of ciphertext and authenticated data:

During the decryption process, the inputs A and C are mapped into the
input of the HMAC algorithm.  It is essential for security that each
possible input to the MAC algorithm corresponds unambiguously to
exactly one pair (A, C) of possible inputs.  The fact that this
property holds can be verified as follows.  The HMAC input is X = A
|| C || len(A).  Let (A,C) and (A',C') denote two distinct input
pairs, in which either 1) A != A' and C = C', 2) C != C and A = A',
or 3) both inequalities hold.  We also let X' = A' || C' || len(A').
In cases 1 and 2, X != X' follows immediately.  In case 3, if len(A)
!= len(A'), then X != X' directly.  If len(A) = len(A'), then X != X
follows from the fact that the initial len(A) bits of X and X' must
be distinct.

in your case C is just the IV and remaining cipher text, of course; in the standard IV is explicitly part of the C.

$\endgroup$
1
  • $\begingroup$ I see, so maybe the answer is that len(A) can safely be placed before A or after C but not in between. And maybe they chose after C to allow A to be streamed? $\endgroup$ Jan 16, 2019 at 1:32

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.