Skip to main content

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ểuMô tả
roundsintSố vòng lặp (ghi đè config)
Option (Argon)KiểuMô tả
memory_costintBộ nhớ sử dụng (KB)
time_costintSố vòng lặp
threadsintSố 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() hay sha1() để 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 rounds theo thời gian khi phần cứng mạnh hơn; dùng needsRehash() để cập nhật hash cũ.
  • Argon2id được khuyến nghị cho dự án mới theo RFC 9106.