Hashing
Module Hashing cung cấp API thống nhất để băm (hash) mật khẩu và các chuỗi nhạy cảm. Framework hỗ trợ ba thuật toán: Bcrypt, Argon2i, và Argon2id — tất cả đều dựa trên hàm password_hash() của PHP.
Cấu hình
File cấu hình nằm tại config/hashing.php:
return [
// Driver mặc định: 'bcrypt', 'argon', 'argon2id'
'default' => env('HASH_DRIVER', 'bcrypt'),
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 12),
],
'argon' => [
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST,
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST,
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS,
],
'argon2_id' => [
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST,
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST,
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS,
],
];
Sử dụng cơ bản
Qua Facade
use Vietiso\Core\Hashing\Facade\Hash;
// Tạo hash từ mật khẩu
$hashed = Hash::make('secret-password');
// Xác minh mật khẩu
if (Hash::check('secret-password', $hashed)) {
// Mật khẩu hợp lệ
}
// Kiểm tra hash có cần tạo lại không
if (Hash::needsRehash($hashed)) {
$hashed = Hash::make('secret-password');
}
Drivers
Bcrypt
Driver mặc định, phù hợp cho hầu hết ứng dụng. Tham số rounds kiểm soát độ phức tạp (cost factor) — giá trị càng cao thì càng an toàn nhưng tốn CPU hơn.
$hashed = Hash::make('my-password');
// "$2y$12$..."
Tuỳ chỉnh số rounds cho từng lần hash:
$hashed = Hash::make('my-password', ['rounds' => 14]);
Kiểm tra xem hash có cần tạo lại theo rounds hiện tại không:
if (Hash::needsRehash($hashed, ['rounds' => 14])) {
$hashed = Hash::make('my-password', ['rounds' => 14]);
}
Argon2i
Thuật toán bộ nhớ-cứng (memory-hard), kháng tấn công GPU tốt hơn Bcrypt. Cần PHP được build với libargon2.
$hashed = Hash::driver('argon')->make('my-password');
Tuỳ chỉnh tham số:
$hashed = Hash::driver('argon')->make('my-password', [
'memory_cost' => 65536, // KB
'time_cost' => 4, // số vòng lặp
'threads' => 2,
]);
Argon2id
Kết hợp Argon2i và Argon2d, được OWASP và RFC 9106 khuyến nghị cho hashing mật khẩu. Dùng khi cần bảo mật cao nhất.
$hashed = Hash::driver('argon2id')->make('my-password');
API giống hệt Argon2i, chỉ khác thuật toán nội bộ (PASSWORD_ARGON2ID).
Chuyển đổi Driver
Dùng Hash::driver() để chọn driver cụ thể trong runtime mà không thay đổi cấu hình mặc định:
// Dùng bcrypt
$hash1 = Hash::driver('bcrypt')->make('password');
// Dùng argon2id
$hash2 = Hash::driver('argon2id')->make('password');
API tham chiếu
make(string $value, array $options = []): string
Tạo hash từ chuỗi đầu vào. Ném RuntimeException nếu thuật toán không được hỗ trợ.
$hashed = Hash::make('my-password');
| Option (Bcrypt) | Kiểu | Mô tả |
|---|---|---|
rounds | int | Số vòng lặp (ghi đè config) |
| Option (Argon) | Kiểu | Mô tả |
|---|---|---|
memory_cost | int | Bộ nhớ sử dụng (KB) |
time_cost | int | Số vòng lặp |
threads | int | Số luồng song song |
check(string $value, string $hashedValue): bool
Xác minh chuỗi gốc có khớp với hash không. Trả về false nếu $hashedValue rỗng hoặc null.
if (Hash::check($request->input('password'), $user->password)) {
// Đăng nhập thành công
}
needsRehash(string $hashedValue, array $options = []): bool
Kiểm tra xem hash có cần tạo lại hay không (thường do thay đổi tham số cấu hình).
// Khi đăng nhập thành công, cập nhật hash nếu cần
if (Hash::needsRehash($user->password)) {
$user->password = Hash::make($plainPassword);
$user->save();
}
info(string $hashedValue): array
Trả về thông tin meta của hash (thuật toán, tham số, v.v.) thông qua password_get_info().
$info = Hash::info($hashed);
// [
// 'algo' => 1, // PASSWORD_BCRYPT
// 'algoName' => 'bcrypt',
// 'options' => ['cost' => 12],
// ]
Ví dụ thực tế
Đăng ký người dùng
use Vietiso\Core\Hashing\Facade\Hash;
$user = new User();
$user->email = $request->input('email');
$user->password = Hash::make($request->input('password'));
$user->save();
Đăng nhập
$user = User::where('email', $request->input('email'))->first();
if (!$user || !Hash::check($request->input('password'), $user->password)) {
return response()->json(['message' => 'Thông tin đăng nhập không hợp lệ.'], 401);
}
// Cập nhật hash nếu cấu hình đã thay đổi
if (Hash::needsRehash($user->password)) {
$user->password = Hash::make($request->input('password'));
$user->save();
}
Đổi mật khẩu
if (!Hash::check($request->input('current_password'), $user->password)) {
return response()->json(['message' => 'Mật khẩu hiện tại không đúng.'], 422);
}
$user->password = Hash::make($request->input('new_password'));
$user->save();
Lưu ý bảo mật
- Không dùng
md5()haysha1()để băm mật khẩu — đây không phải hàm hashing mật khẩu. - Bcrypt tự thêm salt ngẫu nhiên, không cần quản lý salt thủ công.
- Tăng
roundstheo thời gian khi phần cứng mạnh hơn; dùngneedsRehash()để cập nhật hash cũ. - Argon2id được khuyến nghị cho dự án mới theo RFC 9106.