#Nguyên tắc cốt lõi
👉 Không bao giờ lưu password dạng plain text hoặc hash yếu
👉 Rule:
- Hash password → lưu DB
- Verify password → login
#Bad Example (Anti-pattern)
$hash = md5($password);
$hash = sha1($password);
$hash = hash('sha256', $password);
Vấn đề
- Quá nhanh → dễ brute force
- Không có salt đúng chuẩn
- Bị rainbow table attack
#Good Example (Best Practice)
#1. Hash password
$hash = password_hash($password, PASSWORD_ARGON2ID);
#2. Verify password
if (password_verify($input, $hash)) {
// login success
}
#3. Rehash khi cần
if (password_needs_rehash($hash, PASSWORD_ARGON2ID)) {
$hash = password_hash($input, PASSWORD_ARGON2ID);
}
#4. Regenerate session
session_regenerate_id(true);
#5. Custom Argon2
password_hash($password, PASSWORD_ARGON2ID, [
'memory_cost' => 65536,
'time_cost' => 4,
'threads' => 3,
]);
#Giải thích sâu (Senior mindset)
#1. Hashing vs Encryption
- Hash: 1 chiều
- Encrypt: có thể decrypt
👉 Password chỉ nên hash
#2. Argon2id
👉 Memory-hard → chống GPU brute force
#3. Salt
👉 password_hash tự generate salt
#4. Timing attack
👉 So sánh string thường bị leak timing
👉 password_verify an toàn
#5. bcrypt limitation
👉 72 bytes max → cần validate
#Tips & Tricks (Senior level)
#1. Always use PASSWORD_DEFAULT hoặc ARGON2ID
#2. Không tự viết hash
#3. Thêm rate limit login
#4. Không log password
#5. Password reset phải dùng token
#Interview Questions
1. Tại sao không dùng MD5?
Summary:
- Quá yếu
Deep: Dễ brute force và rainbow table
2. password_hash làm gì?
Summary:
- Hash password
Deep: Tự salt + chọn algorithm
3. Argon2id vs bcrypt?
Summary:
- Argon2id tốt hơn
Deep: Memory-hard chống GPU
4. password_verify an toàn ở đâu?
Summary:
- Timing-safe
Deep: Không leak thời gian so sánh
5. password_needs_rehash dùng khi nào?
Summary:
- Khi nâng cấp hash
Deep: Update algorithm/cost
#Kết luận
👉 Password hashing là tuyến phòng thủ quan trọng nhất
Nếu sai → toàn bộ user bị compromise
👉 Luôn:
- password_hash
- password_verify
- Argon2id
- Rehash khi cần