TL;DR
Salts should be random for strong cyber security. While deriving a salt from a passphrase is possible, it’s generally less secure than using a dedicated random number generator. If you must derive, use a robust key derivation function (KDF) like Argon2 or scrypt.
What is a Salt?
A salt is a random piece of data added to a password before hashing it. It prevents attackers from using pre-computed tables of common passwords and their hashes (rainbow tables). Even if two users have the same password, different salts will result in different hashes.
Why Random Salts are Best
- Unpredictability: A truly random salt makes it very difficult for attackers to guess or recreate.
- Rainbow Table Resistance: Each password gets a unique hash even if the passwords themselves are identical.
- Security Standards: Most modern cyber security best practices recommend using randomly generated salts.
Generating Random Salts
Most programming languages and systems provide functions for generating cryptographically secure random numbers.
- Python: Use the
secretsmodule.import secrets salt = secrets.token_hex(16) # Generates a 32-character hex string (16 bytes) print(salt) - PHP: Use
random_bytes()and then encode it.$salt = bin2hex(random_bytes(8)); // Generates an 8-byte salt, encoded as a hex string echo $salt; - JavaScript (Node.js): Use the
cryptomodule.const crypto = require('crypto'); salt = crypto.randomBytes(16).toString('hex'); console.log(salt);
Deriving Salts from Passphrases (Not Recommended)
While not ideal, you might need to derive a salt if storing random salts isn’t feasible. This is less secure than using truly random salts.
- Key Derivation Functions (KDFs): If deriving from a passphrase, always use a KDF like Argon2, scrypt, or PBKDF2.
- These functions add computational cost and salt internally to make cracking harder.
- Never directly hash the passphrase as your salt!
Example Deriving a Salt (Argon2 – Python)
You’ll need the argon2-cffi library: pip install argon2-cffi.
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash('my_secret_passphrase')
salt = hash[:32] # Extract the salt from the hash (Argon2 includes it)
print(salt)
Salt Length
- Minimum: 16 bytes (128 bits).
- Recommended: 32 bytes (256 bits) or more.
Storing Salts
- Store salts alongside the password hashes in your database.
- Treat salts as sensitive data – protect them like passwords.
Important Considerations
- Uniqueness: Each password must have a unique salt. Reusing salts defeats their purpose.
- Length: Use sufficiently long salts to prevent brute-force attacks.