Giải Mã Bí Ẩn: Bcrypt Xác Minh Mật Khẩu 'Thần Kỳ' Kiểu Gì?

Giải Mã Bí Ẩn: Bcrypt Xác Minh Mật Khẩu 'Thần Kỳ' Kiểu Gì?

Lê Lân profile pictureLê Lân
0

Giải Mã Cách Thức Xác Thực Thuật Toán Băm (Hashing Algorithm) Trong Bảo Mật Mật Khẩu



Mở Đầu

Bạn đã bao giờ tự hỏi làm thế nào các thuật toán băm có thể xác thực mật khẩu mà không cần lưu trữ mật khẩu gốc chưa? Đây chính là một trong những câu hỏi quan trọng nhất trong bảo mật thông tin.
Trong thế giới số hiện nay, khi bạn đăng nhập vào một trang web, mật khẩu của bạn không được lưu thẳng mà thường trải qua một hàm băm một chiều (one-way hashing function). Điều này đảm bảo rằng chỉ có chính bạn biết mật khẩu nguyên bản của mình, ngay cả chủ sở hữu máy chủ cũng không thể biết mật khẩu gốc. Khác với mã hóa (encryption) có thể giải mã, băm là một quá trình một chiều, tức là sau khi băm, không thể khôi phục lại dữ liệu ban đầu.
Bài viết này sẽ giúp bạn hiểu rõ cơ chế hoạt động của thuật toán băm, đặc biệt là cách các thuật toán bảo mật tiên tiến như BCrypt thực hiện việc xác thực mật khẩu mà không cần so sánh trực tiếp giá trị băm, từ đó giúp bạn hiểu tường tận về quy trình bảo mật trong hệ thống đăng nhập hiện đại.

Hiểu Về Thuật Toán Băm Và Cơ Chế Hoạt Động

Thuật Toán Băm Là Gì?

Thuật toán băm là một phương pháp chuyển đổi dữ liệu từ dạng ban đầu sang một giá trị đặc biệt, thường có độ dài cố định, dưới dạng chuỗi ký tự khó đoán. Việc này giúp bảo vệ dữ liệu gốc khỏi bị truy xuất trực tiếp.

Ví Dụ Minh Họa Cơ Bản

Giả sử mật khẩu của bạn là  pass123 . Một thuật toán băm đơn giản có thể biến mỗi ký tự của mật khẩu sang một ký tự khác theo quy tắc:
  •  p  m 
  •  a  c 
  • ... và tiếp tục cho đến hết chuỗi
Ví dụ,  pass123  có thể trở thành  D32rASDF . Quan trọng là quá trình này không thể đảo ngược: nếu  p  trở thành  m , thì  m  không nhất thiết phải quay lại thành  p .

So Sánh Hash Đơn Giản

Thông thường, xác thực mật khẩu có thể làm như sau:
if (hash(input_password) === hash(stored_password_in_database)) {
// user login succeed
}
Tuy nhiên, với các thuật toán mạnh như bcrypt, Argon2, thì mỗi lần băm cùng một mật khẩu sẽ cho ra kết quả khác nhau.
Password đầu vào
Kết quả băm 1
Kết quả băm 2
pass123


12$G/bzOjiOAeFTHhvvImkRMeXQ...


12$e1sitHZPq0KFuJ.G9dOmn.wKtf...
Điều này có nghĩa là bạn không thể so sánh băm một cách trực tiếp như ví dụ phía trên.

Cách Xác Thực Trong Thuật Toán Băm Mạnh Như BCrypt

Chi Tiết Về Salt Và Cost Trong Bcrypt

Thuật toán bcrypt không chỉ biến mật khẩu mà còn thêm vào một giá trị ngẫu nhiên gọi là salt cùng với biến cost quyết định độ phức tạp tính toán.
  • Salt: Một chuỗi ký tự ngẫu nhiên làm tăng tính đa dạng trong băm, giúp ngăn chặn các cuộc tấn công dò tìm (rainbow table).
  • Cost: Biến định mức đo lường tài nguyên cần thiết để tạo ra giá trị băm, được tính theo số vòng lặp tăng dần (2^cost).
Theo  Wikipedia , cấu trúc chuỗi băm bcrypt như sau:
Thành phần
Mô tả
 $2a$ 
Xác định thuật toán bcrypt
 [cost] 
Mức cost (ví dụ
 12 
)
 [22 ký tự salt] 
Salt được mã hóa base-64
 [31 ký tự hash] 
Hash thực tế được mã hóa base-64
Ví dụ chuỗi băm:
$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
  •  $2a$ : Thuật toán bcrypt
  •  12 : Cost = 2^12 vòng đếm
  •  R9h/cIPz0gi.URNNX3kh2O : Salt
  •  PST9/PgBkqquzi.Ss7KIUgO2t0jWMUW : Hash
Điều quan trọng là bcrypt lưu trữ cùng lúc thuật toán, cost, salt và hash trong một chuỗi, cho phép xác thực mà không cần giữ riêng từng thành phần.

Ví Dụ Minh Họa Mã Nguồn

import bcrypt from "bcryptjs";

const inputPassword = "pass123";

function bcryptHash(input) {
const cost = 12;
const salt = bcrypt.genSaltSync(cost);
const hash = bcrypt.hashSync(input, salt);
return hash;
}

const result = bcryptHash(inputPassword);
console.log(result);
// Ví dụ kết quả:
// $2b$12$XfT3eq.O3t.NeklIEbzgKOfLZZgHSrYSBKNk5.f5IngnP/Z6/Xo/u
Mỗi lần gọi sẽ cho ra một kết quả khác nhau do salt ngẫu nhiên được sinh.

Cách Xác Thực Mật Khẩu Với Bộ Salt Cũ

Khi một người dùng đăng nhập lại, bạn cần lấy ra  salt  từ chuỗi hash trong cơ sở dữ liệu để tái tạo hash:
const storedPassword = "$2b$12$FSmg5sXtB.XdJH2fFTrV7uBVKaiSdueu7FUcGSTXhoBnPssrjPvmC";

const salt = storedPassword.substring(0, 29); // lấy thuật toán + cost + 22 ký tự salt

const inputHash = bcrypt.hashSync(inputPassword, salt);

if (inputHash === storedPassword) {
// user login succeed
}
Nhờ vào việc sử dụng cùng một salt và cost đã lưu, bạn sẽ nhận được kết quả băm duy nhất và chính xác để so sánh!

Những Điều Cần Lưu Ý Khi So Sánh Hash

So Sánh An Toàn

  • Dù giá trị hash được tạo lại có kết quả cố định sau khi tái tạo với salt cũ nhưng bạn có thể sử dụng các hàm so sánh an toàn chống tấn công timing attack.
  • Tuy nhiên, do bản chất của bcrypt và salt nên việc so sánh trực tiếp bằng  ===  cũng đã đủ an toàn trong hầu hết trường hợp.

Ưu Điểm Của Thuật Toán Hash Mạnh

  • Chống lại các cuộc tấn công dò mật khẩu (brute force attack).
  • Không lưu trữ mật khẩu gốc, bảo vệ thông tin người dùng.
  • Độ phức tạp có thể điều chỉnh bằng  cost  giúp cân bằng an ninh và hiệu năng.

Kết Luận

Qua bài viết, bạn đã hiểu được rằng các thuật toán băm như bcrypt không phải đơn thuần chỉ băm mật khẩu rồi so sánh trực tiếp mà còn kết hợp yếu tố ngẫu nhiên (salt) cùng tham số cost để tạo ra độ bảo mật cao.
Việc lưu trữ chuỗi băm đầy đủ với thuật toán, cost và salt cho phép tái tạo hash chính xác để so sánh khi xác thực người dùng mà không lo bị rò rỉ mật khẩu gốc. Đây chính là bí quyết để hệ thống đăng nhập hiện đại vừa bảo mật vừa tiện dụng.
Nếu bạn đang phát triển hệ thống bảo mật hoặc học về bảo mật thông tin, hãy áp dụng những nguyên tắc này để đảm bảo an toàn tuyệt đối cho dữ liệu người dùng!



Tham Khảo

  1. K. Provos and D. Mazieres, A Future-Adaptable Password Scheme, USENIX Annual Technical Conference, 1999.
  1. OWASP Foundation, Password Storage Cheat Sheet, 2024.
  1. Y. Kim, Understanding Password Hashing, InfoSec Institute, 2023.
Loading...