Random salt and PBKDF2 key

Suppose I wrote a function $$(salt,IV ) = \text{keyIVGenerator}(passwd)$$ which generates a random salt of size 32-bytes and a random Initialisation Vector (IV) of size 16-bytes. Then, use a Key Derivation Function (KDF) like PBKDF2 to generate a key of length 32 bytes (dkLen=32).

$$key = PBKDF2(password, salt, deLen)$$

I created a function $$c = encryption(key,data,IV)$$, assume that padding of data (using aes CBC) is correctly done and logic is right.

When I ask the user for encryption and data, I pass the password to the function $$keyIVGenerator(passwd)$$ to get the $$IV,key$$, and $$passwd$$ them to the $$encryption(key,data,iv)$$ along with data. The encryption works.

And now suppose I have to decrypt the data I will need to pass the same key as generated by PBKDF2 for encryption to decrypt my data. The iv was prepended to the ciphertext.

But what about the salt.

If I pass the password requested from the user to $$keyIVGenerator(passwd)$$ it will generate a new key with the new random salt, hence the data won't be decrypted.

Am I supposed to prepended my salt to the ciphertext too? Should I keep a database of salts?

How do I generate the same key from PBKDF2?

• @kelalaka Yeah, thanks :) – bro Oct 22 '20 at 14:51

1 Answer

Yes, generally the salt is prefixed to the ciphertext.

In principle you always generate a new key for each salt, so you might not need the IV. I would however use the output of PBKDF2 to create a randomized IV and key just to be sure (e.g. using SHA-512 and then use the leftmost 32 for the key and the next 16 bytes for the IV).

It is also possible to use HKDF on the output of PBKDF2 to split off both the data key and IV from the generated intermediate key (that's more neat, but also harder to implement).

Notes:

• It would be a good idea to use an authenticated mode such as GCM. In that case the IV should be 12 bytes.
• dkLen is specified to be in bits, not bytes - at least in the standard. Key sizes generally are.
• A salt of 16 bytes is generally plenty, but 32 bytes is OK too (it should still fit in a single block of even SHA-256, so it will likely not influence the work factor created by the hash function and iteration count).
• I added the salt to the cipher text, like: $filesize+salt+iv+ciphertext$ – bro Oct 22 '20 at 15:09
• And I have a doubt, suppose I pad the cipher block, the last block, by inserting chr(remaining_bytes)*remaining_bytes at the end of block. And encrypt the data. And when it comes to decrypting I don't unpad the data, but I truncate the file by the original file size truncate(original size) (original size before the encryption). Will this work? Is it right? – bro Oct 22 '20 at 15:24
• Sure. But you might as well use optional zero padding if you know the file size in advance, and simply resize the decrypted plaintext instead of performing unpadding. Or, if you choose to use e.g. GCM authenticated mode you would not need any padding at all. Most modes don't require padding, only ECB and CBC require full blocks of plaintext (and then there is ciphertext stealing / CTS for those too). – Maarten Bodewes Oct 22 '20 at 17:00
• hey, if i truncate the file the decrypted file becomes unreadable, 'invalid byte sequence in conversion input' or 'not utf-8 valid', the text files are ok but any other special files like pdf, or py don't work after decryption. Why is the byte sequence messed up? – bro Oct 28 '20 at 6:03
• Sorry, although my avatar is actually looking through the screen at you (it's an owl behind a keyboard) I cannot debug from a distance. I'm not looking at a crystal ball or anything :) – Maarten Bodewes Oct 28 '20 at 9:43