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:
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)
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)
Fetch data from storage
cipher, iv, mac = getValuesFromServer()
new_mac = hmac(iv + cipher, alg:sha256, key:mac_key)
if(mac != new_mac) throw 'Failed MAC check!'
Do AES decrypt
plaintext = aesDecrypt(cipher, iv, mode:cbc, key:enc_key)
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 done
cipher + ivinstead?