この記事で理解したいこと
bcrypt
では、同じパスワードでも毎回異なるハッシュが生成されます。
そんなことは既に知っているという方はブラウザバックでOKです👌
概要レベルでの理解で済ませていた私はこの前提動作を理解しておらず、検証に想定外の時間を使ってしまいました。
自戒の念を込め、記事執筆に至りました。
bcryptとは?
パスワードを安全にハッシュ化するための関数です。
ソルトを自動的かつランダムに生成し、内部的にパスワードとソルトを組み合わせてハッシュ化します。
レインボーテーブル攻撃などに強く、安全性の高いパスワード管理を実現できます。
異なるハッシュが生成される理由
bcrypt
はパスワードをハッシュ化する際にランダムなソルトを使用します。
そのため、同じパスワードでも毎回異なるハッシュが生成されます。
Rubyのコードで動作確認してみます。
require 'bcrypt'
password = "P@ssw0rd!"
str1 = BCrypt::Password.create(password)
str2 = BCrypt::Password.create(password)
puts str1 # $2a$12$NqF3kvqv5GwtZTR7fTk6QuxrM.GG3cFGKRHe9B2fKl/RlEZCX16X.
puts str2 # $2a$12$CX6qZmuq75J6665a.NnHCueeS8iF9UxwXb5v5slWaB1luPl.Z/hIy
上記str1
とstr2
は同一の文字列ですが、異なるハッシュが作成されています。
bcryptのハッシュ構造
bcryptで生成されるハッシュは、以下のようなフォーマットを持っています
$2b$<コスト>$<ソルト><ハッシュ>
例)
$2b$12$eImiTXuWVxfM37uY4JANjQ==8C8eXjJ3bO/5pQkQvJ0i9uE.
この構造には以下の情報が含まれています
-
アルゴリズム識別子 (
$2b$
) -
コスト (
12
) -
ソルト (
eImiTXuWVxfM37uY4JANjQ==
) -
ハッシュ結果 (
8C8eXjJ3bO/5pQkQvJ0i9uE.
)
認証プロセス
パスワードの検証時には、以下の手順が踏まれます。
-
保存されたハッシュからソルトとコストを抽出する:
ハッシュには、ソルトとコストが含まれているため、これらの情報を取得 -
入力されたパスワードに対して同じソルトとコストを使用してハッシュを生成する:
抽出したソルトとコストファクターを用いて、入力されたパスワードをハッシュ化 -
生成されたハッシュと保存されているハッシュを比較する:
生成されたハッシュと保存されているハッシュが一致すれば、正しいと判断
まとめ
- ハッシュ化のタイミングでランダムなソルトが付与されるため、異なるパスワードが生成される
- ソルトがハッシュに組み込まれているため、検証時には同じソルトを使用した認証が可能になっている