Regardless of the KDF I will use, let's imagine that I have to generate two keys: one for authentication and the other for encryption (which will always remain on the device that generates it until logout). Of course, the key I use to encrypt and decrypt must always be the same.

I read some answers on this site that suggested generating a random salt for both keys and saving it with these (preferably separate). But there is a problem: when the user has to decrypt the data or authenticate himself, he will need this precise salt, which must be taken from the database. Since he isn't yet authenticated, how can I trust those who ask me for this salt? Because if I gave it to anyone who asks for it, it wouldn't make sense to use it.

Maybe I am wrong about some considerations since I am a newbie. If I am not mistaken in my assumptions, how can I resolve this stalemate? I have read that some recommend using the hash of the email or username as a salt in these situations. Is it a good practice? Consider that anyone on the client-side can see what I do on the data.

  • 2
    $\begingroup$ In any context in cryptography the salt is not secret. Why one needs the salt for authentication? The user submits the password and the application server get the salt and processes password from the DB and compare with the user entered's process with the salt from the DB. $\endgroup$
    – kelalaka
    Commented May 3, 2020 at 18:38
  • $\begingroup$ So I can assume that at one endpoint like my.secureapp.org/user/salt/[email protected] i can get it? Without restriction $\endgroup$ Commented May 3, 2020 at 20:41

2 Answers 2


Since he isn't yet authenticated, how can I trust those who ask me for this salt? Because if I gave it to anyone who asks for it, it wouldn't make sense to use it.

That's where you went wrong. Salts are public: their purpose is to be unique per derived key, not to be secret. The security analysis of the KDF must assume that any salt used is public, so publishing them to anyone who asks is safe. That's one of the defining properties of a salt, as opposed to a "pepper". Peppers tend to provide no benefit that can't be provided by increasing the cost parameters, and complicate storage, so they're not used much.


If you're thinking along the lines of keeping the salt secret, then it sounds like you may want your users to provide a second factor at time of authentication (ie. 'something you have' and 'something you know').

If the user's device is a phone, and your login screen is a phone-app, then the 'salt' 2nd-factor could be a QRcode that gets scanned by the user when they're logging in (eg. scan QRcode then punch in password/ passcode/ pin/ etc). There are many QRcode scanners out there that, while useful in themselves, would also give you a starting point for coding this functionality into your app. (For eg. SecScanQR on F-droid, https://f-droid.org/en/packages/de.t_dankworth.secscanqr/)

If the login screen is a browser, there's plenty of good phone-apps that will scan a QRcode and tell you the embedded data, so that you might type it into the form. (This probably isn't super-friendly: a time-based second factor, eg TOTP https://www.rfc-editor.org/rfc/rfc6238, might be more appropriate in this case, and, an open-source token manager Android apk called andOTP - https://f-droid.org/en/packages/org.shadowice.flocke.andotp/). There are TOTP implementations in just about every language that web-server logic can be built in.

As kelalaka and SAI Peregrinus both mentioned, you would store the salt against the user account. When the user attempts an authentication, you would combine this salt with the password they provide, and then hash and compare. Peppers could be worth the effort if your authentication server is separate from your storage provider, and you want to add extra entropy to your users' passwords and/or you don't want to completely trust your storage provider: Argon2 allows for a secret key in addition to the password and the salt, more: https://tools.ietf.org/id/draft-irtf-cfrg-argon2-05.html#rfc.section.3 .. sadly most of the (Python) implementations that I've encountered don't expose the secret key or the associated data inputs, as part of their 'easy' (or any) programmer's interface.


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.