1. はじめに
Laravelでハッシュ関数を利用する際、bcrypt()
を使っています。具体的にどういう処理が走っているのか、セキュリティに問題ないのかが気になり調べてみました。
2. 対象読者
- Laravelを使った開発者
- 暗号やセキュリティに興味がある方
3. 目次
4. バージョン
- Laravel 9.x
5-1. bcrypt()
について
bcrypt()
はヘルパ関数の1つです。
概要と使い方は日本語訳されたLaravelドキュメントに記載があります。
bcrypt
関数はBcryptを使用して指定された値をハッシュします。この関数は、Hash
ファサードの代わりに使用できます。
$password = bcrypt('my-secret-password');
5-2. 内部処理
では実際に内部処理について見ていきます。
まずbcrypt()
の定義は下記となります。
function bcrypt($value, $options = [])
{
return app('hash')->driver('bcrypt')->make($value, $options);
}
ドキュメントの記載の通りの処理であることが分かります。
実装ではmake()
メソッドを呼び出しているので、make()
メソッドは下記となります。
public function make($value, array $options = [])
{
$hash = password_hash($value, PASSWORD_BCRYPT, [
'cost' => $this->cost($options),
]);
if ($hash === false) {
throw new RuntimeException('Bcrypt hashing not supported.');
}
return $hash;
}
上記の実装を確認すると、password_hash()
を使っていることが分かります。
こちらはPHPの組み込み関数です。
password_hash(string $password, string|int|null $algo, array $options = []): string
ドキュメントの例のようにbcrypt('my-secret-password');
に使用する場合は、password_hash()
を$algo=PASSWORD_BCRYPT
で使うことを意味します。動作としては、PHPのドキュメントを抜粋します。
PASSWORD_BCRYPT - CRYPT_BLOWFISH アルゴリズムを使ってハッシュを作ります。これは標準の crypt() 互換のハッシュで、識別子
"$2y$"
を使った場合の結果を作ります。 その結果は、常に 60 文字の文字列になります。失敗した場合に false を返します。
また、options
を省略した場合の動作は下記となります。
省略した場合は、パスワードをハッシュするたびに password_hash() がランダムなソルトを自動生成します。これは意図したとおりの操作モードです。
これより、ランダムなソルトが自動生成されるのでレインボーテーブル攻撃に対して有効だと考えられます。
6. さいごに
調べてみるとbcrypt()
は複雑な処理をしているのではなく、組み込み関数であるpassword_hash()
を呼び出していました。また、ハッシュされた文字列に対する攻撃の1つであるレインボーテーブル攻撃に対しても有効であることが分かりました。
ハッシュに関してLaravelでは他にもサポートしているアルゴリズムがありますので、時間があるときに調べてみたいと思います!