TL;DR
Users should never store passwords directly. Always use a strong hashing function with salting to protect them. This guide explains how and why.
Why Not Just Store Passwords?
Storing passwords in plain text is incredibly dangerous. If your system gets hacked, all user accounts are compromised immediately. Hashing makes it much harder for attackers to get useful information even if they steal the password database.
How Password Hashing Works
Hashing takes a password and turns it into a fixed-size string of characters. It’s one-way – you can’t easily get the original password back from the hash. Salting adds random data to each password before hashing, making ‘rainbow table’ attacks much less effective.
Step-by-Step Guide to Secure Password Storage
- Choose a Strong Hashing Algorithm: Don’t use outdated algorithms like MD5 or SHA1. These are easily cracked.
- bcrypt: A good choice, especially for new systems.
- Argon2: Considered very secure and is becoming increasingly popular.
- scrypt: Another strong option.
- Generate Salts: Each password needs a unique salt.
- Salts should be long (at least 16 bytes) and random.
- Store the salt alongside the hashed password in your database.
# Example Python using os.urandom to generate a salt import os salt = os.urandom(16) print(salt) - Hash the Password with the Salt: Combine the password and salt before hashing.
# Example Python using bcrypt import bcrypt password = b'mysecretpassword' salt = os.urandom(16) hashed_password = bcrypt.hashpw(password, salt) print(hashed_password) - Store the Hashed Password and Salt: Save both in your database.
- Don’t store the original password!
- The database column for salts should be a separate field from the hashed password.
- Password Verification: When a user logs in, hash their entered password with the stored salt and compare it to the stored hash.
# Example Python using bcrypt import bcrypt stored_hash = b'$2b$12$EXAMPLEHASHEDPASSWORD' entered_password = b'mysecretpassword' salt = os.urandom(16) #Retrieve salt from database if bcrypt.checkpw(entered_password, stored_hash): print("Password matches!") else: print("Incorrect password.") - Regularly Review and Update: cyber security is constantly evolving. Keep your hashing libraries up to date and consider re-hashing passwords with stronger algorithms as they become available.
Important Considerations
- Key Stretching: Algorithms like bcrypt, Argon2, and scrypt automatically perform key stretching (repeatedly hashing the password) which makes cracking harder.
- Database Security: Protect your database! Hashing is useless if an attacker can directly access it. Use encryption at rest and in transit.
- Rate Limiting: Implement rate limiting on login attempts to prevent brute-force attacks.