Exploring Methods to Hash Passwords: SHA-256, bcrypt, scrypt, Argon2 & more
Hashing passwords before saving them in a database is crucial for security. Here are several methods to hash passwords, each with its pros and cons:
1. SHA-256
Pros: Widely adopted and available in many programming languages. Cons: Fast hashing makes it susceptible to brute-force attacks without proper salting and iterations.
import hashlib
def hash_password_sha256(password: str) -> str:
sha_signature = hashlib.sha256(password.encode()).hexdigest()
return sha_signature
# Usage
hashed_password = hash_password_sha256("my_secure_password")
2. bcrypt
Pros: Specifically designed for password hashing, includes a salt automatically. Cons: Slower compared to some other hashing methods (which is also a security feature).
import bcrypt
def hash_password_bcrypt(password: str) -> str:
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
return hashed.decode()
# Usage
hashed_password = hash_password_bcrypt("my_secure_password")
3. scrypt
Pros: Very memory-intensive, making it more resistant to GPU-based attacks. Cons: Similar libraries are not as common as bcrypt.
import hashlib
import os
def hash_password_scrypt(password: str) -> str:
salt = os.urandom(16)
hash = hashlib.scrypt(password.encode(), salt=salt, n=16384, r=8, p=1)
return salt + hash
# Usage
hashed_password = hash_password_scrypt("my_secure_password")
# Store as base64 for easier database storage
import base64
hashed_password_b64 = base64.b64encode(hashed_password).decode()
4. Argon2
Pros: The winner of the Password Hashing Competition. Cons: Slightly more complex API, but increasing support in modern libraries.
from argon2 import PasswordHasher
def hash_password_argon2(password: str) -> str:
ph = PasswordHasher()
hashed = ph.hash(password)
return hashed
# Usage
hashed_password = hash_password_argon2("my_secure_password")
5. PBKDF2 (Password-Based Key Derivation Function 2)
Pros: NIST recommended, flexible (can increase iterations). Cons: Not memory-hard as scrypt or Argon2.
import hashlib
import os
def hash_password_pbkdf2(password: str) -> str:
salt = os.urandom(16)
hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return salt + hash
# Usage
hashed_password = hash_password_pbkdf2("my_secure_password")
# Store as base64 for easier database storage
import base64
hashed_password_b64 = base64.b64encode(hashed_password).decode()
6. Cryptographic Libraries
Utilize other well-established cryptographic libraries provided by various programming languages, which often have built-in safety and additional features.
Example using Python's passlib:
from passlib.context import CryptContext
# Define password hashing context
pwd_context = CryptContext(schemes=["pbkdf2_sha256", "bcrypt", "argon2"], deprecated="auto")
def hash_password_passlib(password: str) -> str:
return pwd_context.hash(password)
# Usage
hashed_password = hash_password_passlib("my_secure_password")
Advice:
- Always use a salt: It prevents attacks using precomputed hashes (rainbow tables).
- Use built-in libraries: Where possible, rely on well-tested libraries for hashing.
- Iterate: Use multiple iterations to slow down hash computations.
- Upgrade regularly: Stay updated with the latest recommendations and algorithms.
Pick the right tool for your environment and security requirements, and make sure to store and handle your hashed passwords securely.