TL;DR
Using a different, randomly generated ‘salt’ for each password hash makes your cyber security much stronger. It stops attackers using pre-calculated tables (‘rainbow tables’) and speeds up brute-force attacks. Always use unique salts.
Why Salts Matter
When you store passwords, you shouldn’t keep them in plain text! Instead, you ‘hash’ them – turn them into a scrambled code. But simple hashing isn’t enough. If two users have the same password, their hashes will be identical. An attacker could pre-compute hashes for common passwords and quickly find matches.
That’s where salts come in. A salt is random data added to each password before it’s hashed. This means even if two users have the same password, their final hashes will be different because of the unique salt used with each one.
Benefits of Non-Deterministic Salts
- Rainbow Table Protection: Rainbow tables are pre-computed tables of hashes for common passwords. Unique salts make these useless as they need to be re-calculated for every salt value.
- Slower Brute-Force Attacks: An attacker has to try different salts and password combinations, significantly increasing the time and resources needed to crack passwords.
- Increased Security Against Collisions: Although unlikely with good hashing algorithms, collisions (different passwords producing the same hash) are theoretically possible. Salts reduce this risk further.
How to Implement Non-Deterministic Salts
Here’s how you can implement unique salts in practice:
- Generate a Unique Salt: For each new password, generate a random salt. A good length is 16 bytes (128 bits) or more.
- Store the Salt: Crucially, you must store the salt alongside the hash! Don’t keep it secret; it’s meant to be public.
- Hash with the Salt: Combine the password and salt before hashing.
- Verification: When a user logs in, retrieve the stored salt for that user, combine it with the entered password, hash it again, and compare the result to the stored hash.
Example using Python (bcrypt)
The bcrypt library handles salt generation automatically.
import bcrypt
password = b"mysecretpassword"
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password, salt)
print("Hashed password:", hashed_password)
# Verification
if bcrypt.checkpw(password, hashed_password):
print("Password matches!")
else:
print("Password does not match.")
Example using PHP (password_hash)
PHP’s password_hash function also handles salt generation.
<?php
$password = "mysecretpassword";
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
echo "Hashed password: ". $hashed_password . "n";
// Verification
if (password_verify($password, $hashed_password)) {
echo "Password matches!";
} else {
echo "Password does not match.";
}
?>
Important Considerations
- Hashing Algorithm: Use a strong hashing algorithm like bcrypt, Argon2, or scrypt. These are designed to be slow and resistant to attacks.
- Salt Length: Longer salts are better. 16 bytes (128 bits) is a good starting point.
- Storage Security: Protect the database where you store hashes and salts from unauthorized access.
- Regular Updates: Keep your hashing libraries up to date to benefit from security improvements.