Bcrypt

bcrypt(ビー・クリプト)は、1999年にNiels ProvosとDavid Mazièresによって設計・発表されたパスワードハッシュ関数です。これは、Blowfish暗号を基盤としており、パスワードの安全な保存を目的としています。

bcryptの特徴



ソルトの利用: レインボーテーブル攻撃への対策として、ソルト(ランダムなデータ)をパスワードに追加します。
適応性: 計算能力の向上に対応するため、ハッシュ化の反復回数を調整し、処理速度を意図的に遅くすることができます。これにより、ブルートフォース攻撃への耐性を高めています。
幅広い実装: C、C++、C#、Go、Java、JavaScript、Elixir、Perl、PHP、Python、Rubyなど、多様なプログラミング言語で実装されています。
利用実績: OpenBSDのデフォルトパスワードハッシュアルゴリズムとして採用されているほか、SUSE LinuxなどのLinuxディストリビューションを含む、多くのシステムで利用されています。

背景



bcryptは、Blowfish暗号の鍵設定プロセスに着目し、そのコストをさらに高めることでセキュリティを強化しています。Blowfishは、複数のサブキーを用いており、初期状態から鍵の一部を用いて暗号化し、その結果でサブキーを置き換えるというプロセスを繰り返します。ProvosとMazièresは、このプロセスを発展させ、ソルトとパスワードの両方をサブキーの設定に利用する「Eksblowfish」という鍵設定アルゴリズムを開発しました。

Eksblowfishでは、ソルトとパスワードを交互に鍵として扱い、標準Blowfishの鍵作成アルゴリズムを複数回適用します。これにより、鍵生成の計算量を任意に増やし、ブルートフォース攻撃への耐性を向上させています。

ハッシュ文字列の構造



bcryptでハッシュ化された文字列は、`$2a$`、`$2b$`、または`$2y$`といった接頭辞で始まります。これらの接頭辞は、ハッシュ化に使用されたアルゴリズムの種類を示し、Modular Crypt Formatという形式で記述されていることを示します。接頭辞に続く文字列には、以下の情報が含まれています。

コストパラメータ: キー拡張の反復回数(2のべき乗)を設定します。例えば、コストパラメータが10の場合、2の10乗回(1024回)の反復が行われます。
ソルト: 128ビットのランダムなデータで、Radix-64エンコードにより22文字で表現されます。
ハッシュ値: 184ビットの結果のハッシュ値で、Radix-64エンコードにより31文字で表現されます。

例として、`$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy` というハッシュ文字列を分解すると、コストパラメータが10、ソルトが`N9qo8uLOickgx2ZMRZoMye`、ハッシュ値が`IjZAgcfl7p92ldGxad68LJZdL17lhWy`であることがわかります。

バージョン履歴



bcryptには、いくつかのバージョンが存在します。それぞれのバージョンは、発見されたバグや仕様の変更に対応するために導入されました。

`$2$` (1999年): オリジナルの仕様です。Modular Crypt Formatに従い、Blowfishベースの暗号であることを示します。
`$2a$`: ASCII以外の文字やnull終端の扱いを明確化するために改訂されました。文字列はUTF-8でエンコードされ、null終端が含まれる必要がありました。
`$2x`, `$2y$` (2011年): PHPのbcrypt実装である`crypt_blowfish`のバグ修正に関連して導入されました。`$2x`はバグのある実装を明示的に使い続けることを示し、`$2y`は修正された実装で生成されたハッシュ値を示します。しかし、この変更は`crypt_blowfish`に限定され、他の実装には採用されませんでした。
`$2b$` (2014年): OpenBSDのbcrypt実装のバグ修正に対応するため導入されました。パスワード長が255文字を超えた際にオーバーフローが発生する問題が修正されました。

アルゴリズム



bcryptのアルゴリズムは、Blowfishをベースに、コストの高い鍵設定プロセスである`EksBlowfishSetup`関数を使用しています。基本的な流れは以下の通りです。

1. 初期化: `EksBlowfishSetup`関数を用いて、Blowfishの状態を初期化します。
2. 暗号化: "OrpheanBeholderScryDoubt"という文字列を、初期化されたBlowfishの状態を用いて64回暗号化します。
3. 結果: 暗号化された24バイトのデータが、最終的なパスワードハッシュとなります。

EksBlowfishSetup



`EksBlowfishSetup`関数は、コストパラメータ、ソルト、パスワードを入力として、Blowfishの状態を初期化します。この関数は、以下の手順を実行します。

1. 初期状態の設定: Blowfishの初期状態を設定します。
2. 鍵の拡張: ソルトとパスワードを用いて鍵を拡張し、Blowfishの状態を更新します。
3. 繰り返し: 鍵の拡張プロセスを`2^cost`回繰り返します。

ExpandKey



`ExpandKey`関数は、パスワードとソルトをBlowfishの内部状態に混ぜ合わせる役割を担います。

1. パスワードの混合: パスワードをP配列に混合します。
2. ソルトの利用: ソルトを用いてBlowfish暗号化を行い、P配列の一部を更新します。
3. 繰り返しの暗号化: ソルトと現在の鍵スケジュールを用いて繰り返し暗号化を行い、P配列とS-boxを更新します。

ユーザー入力の扱い



bcryptの実装では、パスワードの最初の72バイトのみを使用することが一般的です。これは、Blowfishの鍵設定アルゴリズムが18個の32ビットサブキー(72バイト)を必要とするためです。ただし、オリジナルのbcrypt仕様では、ユーザー入力の文字列を数値に変換する方法については明確に定義されていませんでした。実装によってこの部分が異なるため、非ASCII文字を含むパスワードの強度が低下する可能性が指摘されています。

関連項目



Argon2: パスワードハッシュ競争で選ばれたアルゴリズム。
Crypt (C)#Blowfish-based scheme crypt: Blowfishベースのパスワード保存・検証方式。
Key stretching: 鍵の強度を高める技術。
PBKDF2: パスワードベースの鍵導出関数
scrypt: メモリハードな鍵導出関数

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。