2
$\begingroup$

I'm a bit new to cryptography and I'm trying to wrap my head around PBKDF2 and AES. As a disclaimer, this is not going to be used in an actual application, I'm just testing things locally as a fun side project.

Right now what I'm trying to do is accept a password from someone to encrypt a message, and decrypt it at a later time.

I was doing the following:

    key = InputPassword()
    salt = RandomSalt()
    self.key = PBKDF2(key, salt, 16)

I would then encrypt with AES. At the later time point, I would run:

    key = InputPassword()
    salt = RandomSalt()
    self.key = PBKDF2(key, salt, 16)

again. Of course, my salt is going to be different each time. The problem seems to be that when the salt is different, AES decryption does not work. Am I therefore supposed to include the salt in the encrypted message? For example send something like: "message = message, salt=salt"? If so, what is the purpose of the salt, and what security benefit does including it confer?

$\endgroup$
2
$\begingroup$
  • One reason is to mitigate from the Rainbow tables which is the work of Oechslin. If everybody uses the same salt, one can build a Rainbow table for cracking everybody's passwords. There are even commercial tables for sale (I'm not advertising them just providing the existence). Using the salt for key derivation and passwords simply kills the usage of Rainbow tables. Rainbow tables are still useful if there is a multi-target attack, especially for block-ciphers.

  • The other not good reason is deriving two different keys by just one password. For example, if you want to encrypt with AES and then HMAC, you will need two keys. By using two salts you can get two keys. The below is from Crypto module of Python.

    $$\operatorname{PBKDF2}(password, salt, count, dkLen, prf)$$

    • The iteration (count) should be larger than 16 to make harder the job of passwords crackers like hashcat. 65536 or depending on the user experience, waiting more than 1 seconds may not be a good experience so you can adjust it according to the system.
    • dkLen is the derived key length with default. It can be increased upto $2^{31}-1$ times the output size of the hash function. You can increase it to derive AES and HMAC key with one salt or you can use domain separation with two salts.
    • Actually, for deriving Multiple Keys can be risky with PBDKF2, once your password is found the two keys are gone. You can use PBKDF2 to generate a key and then use KDF like HKDF, rfc5869 $$key = \operatorname{PBKDF2}(password, salt, 65536, dkLen, \operatorname{SHA256})$$then use the key with HKF for different contexts with context

      $$\operatorname{AES-KEY} = \operatorname{HKDF-Expand}(key, \text{"aes-key"}, 128)$$ $$\operatorname{HMAC-KEY} = \operatorname{HKDF-Expand}(key, \text{"hmac-key"}, 256)$$ In this case, you don't need the Extract mechanisms of HKDF, PBKDF2 does it.

  • If you want to send an encrypted message to someone then the generated key must be sent. For this kind of problem, we have a better alternative like DHKE, libsodium crypto box, or RSA-KEM which are based on public-key cryptography. In RSA-KEM we don't use PBKDF2 to derive a key we use KDF like KDF1 or HDKF.

  • PBKDF2 can be used in the protection of passwords in the login systems or key generation like in Veracypt, disk encryption utility. Veracypt can use the PBKDF2 with RIPEMD160 hash function to derive a Key Encryption Key to decrypt the actual encryption key. The iteration is 327661 for system partitions and 655331 for other containers. In order to, access the files again yo need to use not only your password but also the same parameters; salt, and iteration count. Otherwise, you cannot access the encrypted files. The Veracrypt handles the parameters for you, they are not kept as secret!

    The new alternative for PBKDF2 is the Argon2 which is the Winner of the passwords hashing competition, in 2015. Argon2 can increase the used memory during calculations that can prevent the massive parallel hash calculations with GPUs. Hashcat can calculate

    • 1173.1 kH/s for PBKDF2-HMAC-SHA1 and
    • 277.0 kH/s for TrueCrypt PBKDF2-HMAC-RipeMD160 + XTS 512 bit

    based on Nvidia GTX 1080 hashcat performance. *

note that the salt is not secret, only your password is secret here. Once you use a proper system then the attacker's ability is guessing your password. Therefore you must use strong passwords.


* Unfortunately there is not Argon2 to compare

$\endgroup$
  • $\begingroup$ The purpose of the salt is not to allow deriving multiple keys from the same password. This is a very bad abuse of PBKDF2 which can hurt security. You should use a key-based KDF such as HKDF to derive subkeys with labeled purposes, not repeat PBKDF2 with multiple different salts. $\endgroup$ – Squeamish Ossifrage Oct 23 '19 at 1:25
1
$\begingroup$

Just filling some details of the previous answer

Am I therefore supposed to include the salt in the encrypted message? For example send something like: "message = message, salt=salt"?

Yes. The salt is often sent as part of the ciphertext (e.g. for OpenSSL the salt is first 8 bytes of the ciphertext for password-based ecryption).

In theory you may pass as well the kdf parameters (algorithm, count, ...) but not necessarily, these can be fixed.

If so, what is the purpose of the salt, and what security benefit does including it confer?

As already answered - salt is preventing use of rainbow tables and count should make the dictionary search unfeasible (may fix the count so it takes like 200-300ms to create the key)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.