Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Một trong những lỗi bảo mật nghiêm trọng nhất mà người mới có thể mắc là lưu mật khẩu dạng văn bản thuần hoặc băm bằng thuật toán nhanh như MD5. Khi database bị lộ, kẻ tấn công sẽ có mật khẩu của người dùng, vốn thường được dùng lại ở nhiều dịch vụ khác. Bài này chỉ cách làm đúng.
Quy tắc đầu tiên: server không bao giờ cần biết mật khẩu gốc. Thay vì lưu mật khẩu, ta lưu giá trị băm (hash), kết quả của hàm một chiều không thể đảo ngược. Khi đăng nhập, ta băm mật khẩu người dùng nhập và so với giá trị đã lưu.
Mã hóa hai chiều (có thể giải mã) không phù hợp, vì ai có khóa là lấy lại được mật khẩu thật. Với mật khẩu, hãy dùng băm.
MD5, SHA-1, SHA-256 được thiết kế để nhanh. Với kẻ tấn công, nhanh là lợi thế: một card đồ họa có thể thử một lượng khổng lồ mật khẩu mỗi giây. Chúng còn bị tấn công bằng bảng băm dựng sẵn (rainbow table) nếu không có muối. Mật khẩu cần một hàm băm cố ý chậm và tốn bộ nhớ.
Muối là chuỗi ngẫu nhiên duy nhất cho mỗi mật khẩu, được ghép vào trước khi băm. Nhờ vậy hai người dùng cùng mật khẩu vẫn có hai giá trị băm khác nhau, và bảng băm dựng sẵn mất tác dụng. Muối không cần giữ bí mật; các thuật toán hiện đại tự sinh và lưu nó cùng kết quả băm trong một chuỗi.
Hãy dùng chức năng có sẵn trong ngôn ngữ hoặc framework thay vì tự cài đặt.
// PHP$hash = password_hash($password, PASSWORD_DEFAULT);if (password_verify($input, $hash)) { /* đúng */ }if (password_needs_rehash($hash, PASSWORD_DEFAULT)) { /* băm lại */ }// Laravel$hash = Hash::make($password);Hash::check($input, $hash);# Python (thư viện bcrypt)import bcrypthashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))ok = bcrypt.checkpw(input.encode(), hashed)// Node.js (thư viện bcrypt)const bcrypt = require('bcrypt');const hash = await bcrypt.hash(password, 12);const ok = await bcrypt.compare(input, hash);Hàm kiểm tra so sánh theo thời gian không đổi, tránh lộ thông tin qua độ trễ. Đừng tự so sánh hai chuỗi băm bằng toán tử thông thường.
Nếu hệ thống cũ lưu MD5, hãy chuyển dần: khi người dùng đăng nhập, kiểm tra bằng cách cũ rồi lập tức băm lại bằng thuật toán mạnh và lưu thay thế. Với tài khoản lâu không đăng nhập, cân nhắc yêu cầu đặt lại mật khẩu. Nếu nghi ngờ dữ liệu đã lộ, thông báo cho người dùng và buộc đổi mật khẩu.
Độ chậm của hàm băm là thứ bạn điều chỉnh được. Với bcrypt đó là số vòng (cost), với Argon2 là bộ nhớ, số lần lặp và độ song song. Mục tiêu là mỗi lần băm mất khoảng vài chục đến vài trăm mili giây trên server của bạn: đủ chậm để kẻ tấn công thử hàng tỷ mật khẩu là bất khả thi, nhưng đủ nhanh để đăng nhập không bị cảm nhận là chậm. Hãy đo trên phần cứng thật và xem lại tham số định kỳ vì máy móc ngày càng mạnh. Nhờ tính năng băm lại khi đăng nhập, bạn có thể nâng chi phí dần dần mà không làm phiền người dùng.
Tóm lại: băm bằng Argon2id hoặc bcrypt, dùng muối riêng cho từng mật khẩu (thư viện tự lo), kiểm tra bằng hàm có sẵn và bổ sung giới hạn thử và xác thực hai yếu tố. Chỉ vài dòng code đúng cách có thể bảo vệ hàng nghìn người dùng của bạn.
Muốn học bài bản và có lộ trình rõ ràng? Bạn có thể xem các khóa học trên codebem.com.
Nguyễn Đình Cường
0 comment