6
$\begingroup$

I would like to encrypt some sensitive files on my computer and smartphone so that they remain unreadable even if the computer is stolen.

So far as I'm concerned, AES is the best encryption algorithm, so I would go for it. For the AES, I also need a secret key (or cipher key). Therefore, I need a key derivation function, preferably a password-based one. Obviously, I do not want to store the derived secret key on the computer (or smartphone), otherwise, the encrypted text could be easily decrypted using the secret key.

I have read that Argon2 is considered the best choice for password-based key derivation these days.

Now, in the "argon2 cffi Documentation Release 19.1.0" (January 17, 2019) I have read that "Argon2i uses data-independent memory access, which is preferred for password hashing and password-based key derivation" (page 3). Then, on page 9 I read the very same words about Argon2id: "That makes it [Argon2id] the preferred type for password hashing and password-based key derivation".

Now my first question is: Which of the two types of Argon2 is the best for password-based key derivation?

Further, as per the same document, the argon2.PasswordHasher algorithm "always uses a random salt for hashing". This implies that every time I enter my password to decrypt the file, the hashing algorithm will produce different secret keys, so in no way can I reproduce the secret key to decrypt my file.

Of course, I can store the salt on the computer (or smartphone) but then two other questions arise:

How can I use Argon2 with a predefined salt?

Is there a point in using a salt that is freely accessible (if my data are stolen)?

So, can somebody shed light on how Argon2 can be used as a password-based key derivation function? And what would be the solution to my problem?

$\endgroup$
5
  • $\begingroup$ If securely encrypting some files is your end goal, you're much better off using existing encryption facilities rather than rolling your own. For example, you could just 7zip the files with a password. $\endgroup$
    – Fax
    Mar 9, 2020 at 12:11
  • $\begingroup$ 7zip does not use a strong passphrase stretching algorithm like Argon2 and Scrypt. Annoyingly, many other apps also use very weak key stretching - GnuPG, VeraCrypt. Because of this I wrote my own "external" key stretching script called SlowKDF and later made a better script I called DoubleSlow. I prefer DoubleSlow, but on SlowKDF's page I wrote some interesting comments about GnuPG. Also, KeePassXC is supporting Argon2, but it has an annoying quirk - it stretches the key again before saving. $\endgroup$ Oct 18, 2023 at 23:44
  • $\begingroup$ To further clarify why I think the quirk of the KeePassXC is annoying - I set it to "stretch" for 10 seconds. So, when I login it's acceptable. But when I save modifications to the database it's annoying to wait 10 seconds for the operation to occur. I don't think this is really necessary for security. There should be an option to disable this. I don't see a good reason for not using the same (already stretched) key for the next encryption. The hypothesis of some malware stealing from the RAM is theoretically possible, but unlikely, especially on a single-user system. $\endgroup$ Oct 18, 2023 at 23:49
  • $\begingroup$ ⚠ When using an "external" key stretching script (or keep a strong passphrase to be used with 7zip within a password manager) - beware that the secrets you copy/paste may be written on on the history of your clipboard manager. Also Konsole, Gnome Terminal and similar terminal emulators may write the history on the hard drive (depending on settings). Also beware of ~/.bash_history. In my system it's pointing to /dev/null just in case I type something I don't want recorded on my hard drive (although I use full disk encryption). Typically Android smartphones do not use disk encryption. $\endgroup$ Oct 18, 2023 at 23:55
  • $\begingroup$ To further clarify on the malware hypothesis - if the malware can steal the stretched key it can also steal the passphrase. So it does not make sense to not use the already stretched key for this reason. $\endgroup$ Oct 18, 2023 at 23:58

1 Answer 1

7
$\begingroup$

Which of the two types of Argon2 is the best for password-based key derivation?

In short, as said by draft-irtf-cfrg-argon2-03;

If you do not know the difference between them or you consider side-channel attacks as viable threat, choose Argon2id.

  • Argon2d is faster and uses data-depending memory access. Data dependency immediately enables side-channel. This is suitable for cryptocurrencies and applications with no threats from side-channel attacks.

  • Argon2i uses data-independent memory access and this is preferred for password hashing and password-based key derivations.

  • Argon2id In the first half of the first iteration works as Argon2i and the rest works as Argon2d. This enables both side-channel protection and time-memory trade-off.

How can I use Argon2 with a predefined salt?

From a library for Argon2

    Usage:  ./argon2 [-h] salt [-i|-d|-id] [-t iterations] [-m memory] [-p parallelism] [-l hash length] [-e|-r] [-v (10|13)]
            Password is read from stdin
    Parameters:
            salt            The salt to use, at least 8 characters
            -i              Use Argon2i (this is the default)
            -d              Use Argon2d instead of Argon2i
            -id             Use Argon2id instead of Argon2i
            -t N            Sets the number of iterations to N (default = 3)
            -m N            Sets the memory usage of 2^N KiB (default 12)
            -p N            Sets parallelism to N threads (default 1)
            -l N            Sets hash output length to N bytes (default 32)
            -e              Output only encoded hash
            -r              Output only the raw bytes of the hash
            -v (10|13)      Argon2 version (defaults to the most recent version, currently 13)
            -h              Print argon2 usage

The libraries handle this for you. You just provide a random salt and store it, if you want to get the same result again, use the same salt.

Is there a point in using a salt that is freely accessible (if my data are stolen)?

Normally, you can store these values - salt, iteration, memory usage, parallelization, output size - with your data. If you really want to keep them separately from the storage you can do it, but there is no need. It is designed to be secure even if they are known by an attacker. When servers are attacked, all of these parameters are also acquired by the attackers. Salt is used against rainbows tables. Remember Kerckhoffs's principles, only the key is secret.

Some people suggest making the salt a secret to increasing the security of their product, however, remember that if your security relies on the security of the salt, there is a real problem with your design.

can somebody shed light on how Argon2 can be used as a password-based key derivation function?

There is a Key Encryption Key (KEK) methodology that is common with disk encryption utilities. Let say a file encryption key (FEK) is randomly generated by a good random source. Then your strong password is used to derive the KEK with Password-Based Key Derivation Function (PBKDF), here in your case Argon2id.

$$\text{KEK} = \operatorname{Argon2id}(salt, password)$$ Use your KEK to encrypt FEK and store it on your target ( your computer or phone). $$FEK^* = \operatorname{AES}\hbox{-} Enc_{KEK}(FEK)$$

Now, you want to encrypt a file, use your strong password to generate the KEK

$$\text{KEK} = \operatorname{Argon2id}(salt, password)$$

and use the KEK to decrypt your FEK from the storage.

$$FEK = \operatorname{AES}\hbox{-} Dec_{KEK}(FEK^*)$$

Encrypt the file with an authenticated encryption mode like AES-GCM or ChaCha20-Poly1305 and store it on your computer or cell-phone.

$$\text{EnryptedFile, ATag} = \operatorname{AES}\hbox{-} GCM\hbox{-}Enc_{FEK}(\text{file})$$ where ATag is the authentication tag. Never decrypt a ciphertext if there is tag missmatch, halt!

You need to keep FEK only in system memory and purge it when the operations are finished.

The benefits of this approach;

  • You only need to memorize your strong password
  • The Encrypted FEK and Argon2id parameters can be stored together with the files or some other suitable place for your choice.
  • For each file, you can generate a new random FEK.

always uses a random salt for hashing".

It is for each file or password not for every run of Argon2 run. You need to derive the same results if you want to compare the hash of the file or generate the same key, you have to use the same parameters including the salt. And to not forget that salt, you must write it somewhere.

$\endgroup$
2
  • 1
    $\begingroup$ Thank you very much for your quick and comprehensive answer. Actually, the argon2 cffi Documentation Release 19.1.0 also contains low level functions, such as argon2.low_level.hash_secret, which have a salt parameter, too. However, there is a warning at the beginning of the chapter: "This is a “Hazardous Materials” module. You should ONLY use it if you’re 100% absolutely sure that you know what you’re doing because this module is full of land mines, dragons, and dinosaurs with laser guns." Since I am afraid of dragons, I thought that this module is not for me. :) $\endgroup$
    – K. Gabor
    Oct 14, 2019 at 19:34
  • 1
    $\begingroup$ full of land mines, dragons, and dinosaurs with laser guns :) $\endgroup$
    – kelalaka
    Oct 14, 2019 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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