Using a password with salt is a common best practice for securely storing passwords in a system. It protects against rainbow table attacks by introducing a random value (the salt) to each password before it is hashed.
What Is Salt?
• A salt is a unique, random value that is added to a password before it is hashed.
• It ensures that even if two users have the same password, their hashed values will be different because the salt is unique for each user.
Steps for Storing Passwords with Salt:
1. Generate a Salt:
• Use a cryptographically secure random generator to create a unique salt for each user.
2. Combine Salt and Password:
• Append or prepend the salt to the user’s password.
3. Hash the Combined Value:
• Use a secure hashing algorithm (e.g., SHA-256, bcrypt, Argon2).
4. Store the Salt and Hash:
• Save both the salt and the resulting hash in your database.
• Ensure the salt is stored in plaintext, as it is not secret.
Example Implementation in Python
Here’s an example using Python with the bcrypt library:
Code Example:
import bcrypt
# Function to hash a password with salt
def hash_password(password: str) -> tuple:
# Generate a salt
salt = bcrypt.gensalt()
# Hash the password with the salt
hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
return salt, hashed_password
# Function to verify a password
def verify_password(password: str, salt: bytes, stored_hash: bytes) -> bool:
# Recompute the hash using the provided password and salt
computed_hash = bcrypt.hashpw(password.encode('utf-8'), salt)
return computed_hash == stored_hash
# Example usage
if __name__ == "__main__":
user_password = "SecurePassword123!"
# Hash the password
salt, stored_hash = hash_password(user_password)
print(f"Salt: {salt}")
print(f"Stored Hash: {stored_hash}")
# Verify the password
is_valid = verify_password("SecurePassword123!", salt, stored_hash)
print("Password is valid:", is_valid)
Example Database Storage:
Store the salt and hash separately in your database:
User ID | Salt | Hash |
1 | random_salt_value | hashed_password |
Best Practices:
1. Use a Secure Salt Generator:
• Always use cryptographically secure random number generators for salts.
• In Python, os.urandom() or libraries like bcrypt are recommended.
2. Avoid Weak Hashing Algorithms:
• Do not use MD5 or SHA-1, as they are vulnerable to attacks.
• Use algorithms designed for passwords, such as:
• bcrypt: Adds internal salt and is computationally expensive.
• Argon2: Modern and highly secure (recommended).
• PBKDF2: Widely used and secure.
3. Don’t Reuse Salts:
• Always generate a unique salt for each password.
4. Limit Login Attempts:
• Use rate-limiting or captchas to protect against brute-force attacks.
Why Is Salting Important?
Without a salt:
• Identical passwords will have identical hashes.
• Attackers can use precomputed hashes from rainbow tables to crack passwords.
With a salt:
• Each password gets a unique hash, making it infeasible for rainbow tables to be effective.