I've been doing a lot of reading on the proper way to implement AES CBC mode with HMAC authentication. I've seen many explanations, however, I've had a hard time finding an actual real example (with code) on all steps including key derivation, encryption, and decryption. My application uses PBKDF2 for key derivation. Here is what I have so far:
Derive Keys
Generate 256 bits of "key material" with KDF
key_material = pbkdf2(user_password, salt, iterations, size:256, alg:sha256)
Split key material in half yielding x2 128 bit keys for encryption and signing
enc_key = key_material.split(0, 127) mac_key = key_material.split(128, 255)
Encrypt
Generate 128 bit initialization vector
iv = secureRandomBits(128)
Do AES encrypt
cipher = aesEncrypt(plaintext, iv, mode:cbc, key:enc_key)
Compute MAC with concatenated IV and cipher bits
mac = hmac(iv + cipher, alg:sha256, key:mac_key)
Store resulting values to server (considered unsecure storage)
storeValuesToServer(cipher, iv, mac)
Decrypt
Fetch data from storage
cipher, iv, mac = getValuesFromServer()
Recompute mac
new_mac = hmac(iv + cipher, alg:sha256, key:mac_key)
Compare macs
if(mac != new_mac) throw 'Failed MAC check!'
Do AES decrypt
plaintext = aesDecrypt(cipher, iv, mode:cbc, key:enc_key)
Questions
Does this look correct? Main concerns here are:
- Have I derived the keys correctly, splitting them in half based on the output of the KDF?
- Am I computing the HMAC correctly by combining the
iv + cipher
. Does it matter if I had donecipher + iv
instead?