I am studying an application with an AES crypto implementation that works that like the following:
PBKDF2 is used with X iterations and SHA-256 to generate a 256-bit "master key" from a user-provided password and salt.
master_key = pbkdf2( password, salt, iterations, alg: SHA256, size: 32)
A crytpo-safe RNG is used to generate 512 bits of "key material" .
key_material = random_bytes( size: 64)
The key material is then encrypted with the 256-bit master key, unauthenticated.
encrypted_key_material = encrypt_aes( data: key_material, key: master_key, hmac_key: null, mode: CBC)
The encrypted key material is persisted on the device for later encryption use. The application user only needs to provide the PBKDF2 generated master key to decrypt it.
It should be noted that the
encrypt_aes
function generates and uses a standard 16 byte random IV with every operation which is part of the returned encrypted bytes (along with the computed encrypt-then-mac HMAC data).When the application needs to encrypt some data, half of the key material is used as the encryption key and the other half is used as the HMAC key.
key_material = decrypt_aes( data: encrypted_key_material, key: master_key, hmac_key: null, mode: CBC) encryption_key = key_material.split(0, 31) hmac_key = key_material.split(32, 64)
And now encryption of other data can be performed in the application, which is authenticated.
encrypted_data = encrypt_aes( data: "Hello World", key: encryption_key, hmac_key: hmac_key, mode: CBC) decrypted_data = decrypt_aes( data: encrypted_data, key: encryption_key, hmac_key: hmac_key, mode: CBC) // decrypted_data is now "Hello World"
I understand that CBC mode should always use HMAC authentication to protect against oracle attack vectors. As we can see here, an HMAC is used for encrypting data in the application (step 5), but it is not used when encrypting the random key material (step 3 and 4) that gives access to all of that data. This is presumably this way because PBKDF2-SHA256 does not produce enough bits to supply a 256-bit HMAC key for protecting the key material (step 3), hence why 512 bits of key material is derived separately for further encryption operations.
Is this a safe implementation? Does the fact that the key material is random byte data change its need to have HMAC authentication to protect it from attacks? Is the key material decryption from step 4 subject to the same attack vectors as standard string decryption, as in step 5?