What is the correct way to implement PBKDF2 + AES CBC + HMAC? 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 done cipher + iv instead?
You'll find there's a lot of splitting hairs regarding this topic, especially key derivation. But yes, your pseudocode is fine, although you may want to revise (0, 128) => (0, 127) and (129, 256) => (128, 255) ... (correct me if I'm wrong?). Also, you might want to implement a constant-time comparison function for verifying the mac.


  Have I derived the keys correctly, splitting them in half based on the
  output of the KDF?


This is fine. Some people would disagree. See here here and here for more in-depth discussion.


  Am I computing the HMAC correctly by combining the iv + cipher. Does
  it matter if I had done cipher + iv instead?


Yes, you're computing the HMAC correctly. No, the order of cipher + iv does not matter at all. If it's available to you, you might want to consider a mode like GCM, which takes care of encryption and authentication for you with a single key.