It might seem like a silly exercise, but I was looking at the "NIST approved" algorithms in NaCl (i.e. AES, HMAC) and wondering if I could build an authenticated encryption system with them. djb lists AES-GCM as a "todo" secretbox primitive so unfortunately NaCl does not presently expose any AES-based authenticated encryption, only aes128ctr.
This is what I came up with using the algorithms available in NaCl:
A quick rundown:
Encrypt-then-MAC with AES-CTR (128-bit for now, 256-bit later!) encryption and HMAC SHA-512256 (i.e. SHA-512, truncated to 256-bits by NaCl via crypto_auth_hmacsha512256) authentication. MAC comparisons are performed using a NaCl supplied verifier function which is (hopefully!) constant time.
Separate keys are used for AES and HMAC, derived by combining an initial 256-bit key and a nonce with HKDF and expanding the result into unique keys for AES and HMAC. Because a unique key is used for each AES encryption, the AES counter can always start at 0.
While a cryptographic layman should probably not be designing an authenticated encryption mode, it seems like these particular primitives are relatively free of rough edges, particularly when I am using the implementations available in NaCl
No, you want Crypto::SecretBox
You forgot the nonce in the diagram.
Also, for key derivation, I'd suggest:
which is how Schneier et al suggest doing it in Cryptography Engineering (Chapter 7, iirc). With the string values adjusted to taste. The other alternative is to do as djb does and use the encryption of 0s with the first 32 bytes of the stream as the key for the authenticator.