
bcryptは1999年、OpenBSDプロジェクトの開発者Niels ProvosとDavid Mazièresが発表したパスワードハッシュ関数です。対称鍵暗号Blowfishの鍵スケジュールを拡張した独自方式「Eksblowfish」を内部に持ち、計算コストパラメータを上げるだけで将来のCPU高速化に追随できる「適応的ハッシュ」という発想が画期的でした。MD5やSHA-1を素直にパスワードへ適用する慣習が支配的だった時代に、レインボーテーブル攻撃とブルートフォース攻撃を実用的に困難にし、現在も多くのWebアプリケーションでパスワード保存のデファクト標準として残っています。
この記事の目次
- ソルトとコストファクターによる遅延
- USENIX 1999で発表された経緯
- Webアプリでのパスワード保存
- scrypt・argon2・PBKDF2との比較
- まとめ
ソルトとコストファクターによる遅延

bcryptハッシュは$2b$12$XXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYのような60文字の文字列で、プレフィックスの2bがバージョン、12がコストファクター、続く22文字が128ビットのソルト(base64エンコード)、末尾31文字が192ビットのハッシュ値(base64エンコード)です。コストファクターnを1上げると鍵スケジュールが2倍遅くなり、12なら2^12=4096回のEksblowfishラウンドを実行します。2024年時点の推奨値はサーバー性能に応じて12〜14程度です。
Eksblowfishは、Blowfishのサブキー生成を繰り返しソルトとパスワードで再初期化することで、メモリアクセスパターンを変動させGPU/ASICでの並列攻撃を妨げる設計です。ソルトがハッシュ値に同梱されているため、レインボーテーブル攻撃は事実上無効化され、同じパスワードでも保存される文字列は毎回異なります。CPU負荷が高いことそのものが攻撃者へのコストになるため、「遅いことこそが価値」という逆転の発想がbcryptの本質です。
USENIX 1999で発表された経緯

Niels ProvosとDavid Mazièresは1999年6月のUSENIX Annual Technical Conferenceで論文「A Future-Adaptable Password Scheme」を発表し、bcryptを世に出しました。ベースとなったBlowfishは1993年にBruce Schneierが設計した64ビットブロック暗号で、鍵スケジュールが極端に遅い(数千回のFeistel演算が必要)という性質を逆手に取り、「攻撃者にとって遅いことが防御になる」という適応的ハッシュの構想を実装に落とし込んだのが新しさでした。
OpenBSDはbcryptを即座にcrypt(3)関数に取り込み、システムのパスワード保存方式として採用しました。その後、Ruby(bcrypt-ruby)、PHP(password_hash関数のPASSWORD_BCRYPT)、Python(bcrypt、passlib)、Node.js(bcryptjs、bcrypt)、Java(jBCrypt)など主要言語に移植され、RailsやLaravel、Spring SecurityなどのWebフレームワークがデフォルトで採用したことで一気に普及しました。「パスワードを保存するならbcrypt」という相場観が2010年代前半に定着したのです。
Webアプリでのパスワード保存

bcryptの実務での使い方はシンプルで、ユーザー登録時にハッシュ化してデータベースへ保存し、ログイン時に入力パスワードを同じソルトとコストで再ハッシュして文字列を比較するだけです。Ruby on Railsのhas_secure_password、Laravel/SymfonyのHash::make、Spring SecurityのBCryptPasswordEncoder、Djangoのdjango.contrib.auth.hashers.BCryptSHA256PasswordHasherなど、主要フレームワークが標準で抽象化を提供しています。開発者がアルゴリズムの中身を意識しなくても、デフォルト設定で十分安全なハッシュが得られるようになっています。
注意点として、bcryptはパスワードの先頭72バイトしか使わないという仕様があるため、長すぎるパスフレーズをそのまま投入すると先頭72バイトが同じパスフレーズが衝突します。これを避けるため、Djangoなどは事前にSHA-256でハッシュしてからbcryptへ渡す「bcrypt_sha256」方式を採用しています。また、コストファクターは数年に一度見直し、サーバー性能向上に合わせて12→13→14と段階的に上げ、ログイン時に旧コストを検出したら再ハッシュして書き戻す運用が望ましいとされています。
scrypt・argon2・PBKDF2との比較

bcryptはCPU時間だけを攻撃コストにする設計のため、近年はGPUやFPGAでの並列攻撃に対する耐性が相対的に弱くなっていると指摘されます。これを補うため、2009年にColin Percivalがメモリも大量消費するscryptを発表し、暗号通貨LitecoinのProof-of-Workにも採用されました。2015年にはPassword Hashing CompetitionでArgon2が優勝し、Argon2iやArgon2idといったバリアントが新規プロジェクトの第一選択となっています。
古典的なPBKDF2(RFC 2898、2000年)はSHA-256などの汎用ハッシュを反復するだけのシンプルな方式で、NIST SP 800-132で標準化されているためFIPS認定が必要な金融・政府用途では今も使われます。とはいえ、Webアプリの世界では「新規ならArgon2id、既存ならbcryptで十分」という相場観が主流で、bcryptが20年以上にわたり信頼を維持していることは特筆すべき事実です。アルゴリズム選択で迷ったらArgon2idへ移行し、すでにbcryptで運用しているなら無理に置き換えないというのが現代の定石です。
まとめ
bcryptは「遅さこそが防御」という逆転の発想を実装に落とし込み、ソルトと適応的コストでパスワード保存のデファクト標準を四半世紀にわたり守ってきました。Argon2への移行が推奨される今も、既存システムでの安定運用という観点では依然として有力な選択肢です。
※本記事はIT用語辞典の手書きドラフトです。公開前に最新情報・出典を確認のうえ加筆修正してください。

コメント