I'm writing a program that allows two users to communicate over E2E encrypted chat with a secret they have agreed upon in the past.

The process works as follows:

  1. A key is derived from the secret using Argon2id, where the salt is hardcoded in the application.
  2. The key is used to encrypt the user's message using crypto_secretbox from NaCl.
  3. The message is sent to the server and downloaded by the other user.
  4. The user on the receiving end decrypts the message using the same key derived in the same way.

As I understand it, in a password hashing system, a unique salt per password prevents attacks where the bad guys have pre-computed the hashes for a ton of different passwords.

Would there be any advantage for my application to use a different salt for each user (possibly generated by the server)?

  • 1
    $\begingroup$ The salt is hardcoded in the application? Why? $\endgroup$
    – forest
    Commented Aug 7, 2019 at 3:53

1 Answer 1


You should never re-use a salt, and you should especially not hardcode it for your entire application! A salt has several purposes, including the one you mentioned (defeating rainbow table attacks and others based on precomputation). However, a salt also prevents an attacker from trying to break multiple users' passwords at once. If you use a salt that is not unique, an attacker could trivially build a rainbow table for your application, or attack a batch of users. This is almost as bad as having no salt!

Generally, you want the salt to be exchanged along with the encrypted data or the hash. In this case, you'd want to send the salt and any other unencrypted metadata along with the ciphertext. The salt should be agreed upon by both parties, not generated by the server or any other third party.

With that said, you should not be using an agreed-upon preshared secret password to derive a key for encryption in an end-to-end chat application. The encryption key should be generated using public key encryption. I would recommend using an ECC algorithm like x25519, which is supported by NaCl. The agreed-upon secret should only be used for authentication. That ensures that a weak password does not result in confidentiality loss. You should learn from OTR, which uses SMP for mutual authentication.

  • $\begingroup$ To complement this answer: the documentation of libsodium is clear: "The nonce doesn't have to be confidential, but it should never ever be reused with the same key." NaCl is a low-level library, which should only be used by cryptographers. If possible, you should instead use a higher-level library like libsodium. $\endgroup$
    – A. Hersean
    Commented Aug 7, 2019 at 16:49

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.