bcrypt


Bcrypt

bcryptファイル暗号化ユーティリティについては、Blowfish(暗号)を参照してください
bcryptは、Blowfish暗号に基づいてNiels ProvosとDavidMazièresによって設計され、1999年にUSENIXで発表されたパスワードハッシュ関数です。レインボーテーブル攻撃から保護するためにソルトを組み込むことに加えて、bcryptは適応関数です。反復回数を増やして速度を落とすことができるため、計算能力を高めても、ブルートフォース検索攻撃に対する耐性が維持されます。 bcrypt 全般的
デザイナー
Niels Provos、DavidMazières
初版 1999年 に由来する
Blowfish(暗号)
詳細
ダイジェストサイズ
184ビット
ラウンド
コストパラメータによる変数
bcryptの機能は、デフォルトのパスワードであるハッシュアルゴリズムのためのOpenBSD といくつかのデフォルトたLinuxディストリビューションなど、SUSE Linuxの。
C、C ++、C#、Elixir、 Go、 Java、 JavaScript、 Perl、PHP、Python、 Ruby、およびその他の言語用のbcryptの実装が

コンテンツ
1 バックグラウンド
2 説明
3 バージョン管理の履歴
4 アルゴリズム
4.1 高価なキーの設定
4.2 キーを展開
5 ユーザー入力
6 批判
6.1 パスワードの最大長
6.1.1 解決策1-サブキーの数を増やす
6.1.2 解決策2-キーバイトをPサブキー配列にxorミックスし続けます
6.1.3 解決策3-ハッシュ前のパスワード
6.2 パスワードハッシュの切り捨て
6.3 非標準のbase64エンコーディングの使用
7 も参照してください
8 参考文献
9 外部リンク

バックグラウンド
Blowfishは、その高価なキー設定フェーズでブロック暗号の中で注目に値します。標準状態のサブキーから開始し、この状態を使用してキーの一部を使用してブロック暗号化を実行し、その暗号化の結果(ハッシュでより正確)を使用して一部のサブキーを置き換えます。次に、この変更された状態を使用してキーの別の部分を暗号化し、その結果を使用してさらに多くのサブキーを置き換えます。すべてのサブキーが設定されるまで、段階的に変更された状態を使用してキーをハッシュし、状態のビットを置き換えるという方法で進行します。
ProvosとMazièresはこれを利用し、さらに進めました。彼らは、Blowfishの新しい鍵設定アルゴリズムを開発し、結果として得られた暗号「Eksblowfish」(「高価な鍵スケジュールBlowfish」)を吹き替えました。キーの設定は、標準のBlowfishキー設定の変更された形式で始まります。この設定では、ソルトとパスワードの両方を使用してすべてのサブキーを設定します。次に、標準のBlowfishキーイングアルゴリズムが適用されるラウンドがいくつかあり、代わりにソルトとパスワードをキーとして使用します。各ラウンドは、前のラウンドのサブキー状態から始まります。理論的には、これは標準のBlowfishキースケジュールよりも強力ではありませんが、キーの再生成ラウンドの数は構成可能です。したがって、このプロセスは任意に遅くすることができ、ハッシュまたはソルトに対するブルートフォース攻撃を阻止するのに役立ちます。

説明
bcryptハッシュ文字列の形式は次のとおりです。
$ 2 $ $
例えば:
$ 2a $ 10 $ N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy __ / / ____________________ / _____________________________ /アルグコストソルトハッシュ
どこ:
$2a$:ハッシュアルゴリズム識別子(bcrypt)
10:コストファクター(2 10、つまり1,024ラウンド)
N9qo8uLOickgx2ZMRZoMye:16バイト(128ビット)ソルト、22文字としてエンコードされたRadix-64
IjZAgcfl7p92ldGxad68LJZdL17lhWy:24バイト(192ビット)ハッシュ、31文字としてエンコードされた基数-64
シャドウパスワードファイルのハッシュ文字列のプレフィックス$2a$または$2b$(またはcrypt_blowfish特にPHPパッケージの場合:$2x$および$2y$)は、ハッシュ文字列がモジュラーcrypt形式のbcryptハッシュであることを示します。残りのハッシュ文字列には、コストパラメータ、128ビットのソルト、および192ビットの結果のハッシュ値が含まれます。 Radix-64エンコーディングは、unix / cryptアルファベットを使用し、「標準」のBase-64ではありません。 costパラメーターは、暗号化アルゴリズムへの入力である2の累乗としてキー拡張反復カウントを指定します。
たとえば、シャドウパスワードレコードは$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy2つのを示し、10のコストパラメータを指定する10キーの拡張ラウンドを。ソルトはでN9qo8uLOickgx2ZMRZoMyeあり、結果のハッシュはIjZAgcfl7p92ldGxad68LJZdL17lhWyです。標準的な方法では、ユーザーのパスワード自体は保存されません。
ほとんどのプログラミング言語では、テキストが正規表現を使用してエンコードされたbcryptパスワードを表しているかどうかを確認できます。この機能は、パスワードが正しくエンコードされているかどうかを検証するために使用できます。以下は、ほとんどのプログラミング言語で機能する正規表現のPythonでの例です。
インポート 再#bcryptパスワードに一致する正規表現の簡略化されたバージョンREGULAR_EXPRESSION = 「^ 2 (?:0 | | 3 )? [./ 0-9A-ZA -Z] {53} $ “#バージョン「2y」でエンコードされたコスト12のbcryptパスワードENCODED_PASSWORD = “$ 2Y $ 12 $ PEmxrth.vjPDazPWQcLs6u9GRFLJvneUkcf / vcXn8L.bzaBUKeX4W”一致 = re 。検索(regular_expression 、 encoded_pa​​ssword ) 一致する場合: 印刷(「はい!一致します!」)その他: 印刷(「一致なし」)
このプログラムを実行すると、次の出力が得られます。
はい!試合があります!
指定されたテキストが有効なbcryptパスワードであるかどうかを識別するだけでなく、正規表現を使用して、バージョン、コスト、ソルト、ハッシュなどの情報を抽出できます。以下は、エンコードされたパスワードから情報を抽出する、より高度な正規表現のPythonでの例です。ほとんどのプログラミング言語で動作するように調整できます。
#この例にはPython3.6以降が必要ですインポート 再#bcryptパスワードと一致し、その情報を抽出するための正規表現の高度なバージョンregular_expression = “^ (?P 2 ?)(?P (?P (0 | | 3 )))(?P ((?P [./ 0-9a-zA-Z] {22} )(?P [./ 0- 9a-zA-Z] {31} )))$ “#以下、他の言語で使用するための同じ正規表現#名前から「P」の文字が削除されていることに注意してください##^ (? 2 ?)(?(?(0 | | 3 )))(?((? [./ 0-9a-zA-Z] {22})(? [./ 0-9a-zA-Z] {31 })))$パターン = re 。コンパイル(regular_expression )#バージョン「2y」でエンコードされたコスト12のbcryptパスワードENCODED_PASSWORD = “$ 2Y $ 12 $ PEmxrth.vjPDazPWQcLs6u9GRFLJvneUkcf / vcXn8L.bzaBUKeX4W”一致 = パターン。一致(encoded_pa​​ssword ) 一致する場合: 印刷(「はい!一致します!」) 印刷(”” ) print (f “バージョン:{一致。グループ(’バージョン’ )} ” ) プリント(F “コスト:{一致。グループ(’コスト’ )} ” ) プリント(F “強度(コストのために別の名前):{一致。グループ(’強’ )} ” ) print (f “パスワード:{一致。グループ(’パスワード’ )} ” ) プリント(F “塩:{一致。グループ(’塩’ )} ” ) プリント(F “ハッシュ:{一致。グループ(’ハッシュ’ )} ” )その他: 印刷(「一致なし」)
このプログラムを実行すると、次の出力が得られます。
はい!試合があります!バージョン:2年費用:12強さ(コストの別名):12パスワード:PEmxrth.vjPDazPWQcLs6u9GRFLJvneUkcf / vcXn8L.bzaBUKeX4W塩:PEmxrth.vjPDazPWQcLs6uハッシュ:9GRFLJvneUkcf / vcXn8L.bzaBUKeX4W

バージョン管理の履歴
$ 2 $(1999)
元のbcrypt仕様では、プレフィックスが$2$。で定義されていました。これは、OpenBSDパスワードファイルにパスワードを保存するときに使用されるModular Crypt Format 形式に従います。
$1$:MD5ベースの暗号( ‘md5crypt’)
$2$:Blowfishベースのクリプト( ‘bcrypt’)
$sha1$:SHA-1ベースの暗号( ‘sha1crypt’)
$5$:SHA-256ベースの暗号化( ‘sha256crypt’)
$6$:SHA-512ベースのクリプト( ‘sha512crypt’)
$ 2a $
元の仕様では、非ASCII文字の処理方法も、ヌルターミネータの処理方法も定義されていませんでした。仕様が改訂され、文字列をハッシュするときに次のように指定されました。
文字列はUTF-8でエンコードされている必要があります
ヌルターミネータを含める必要があります
この変更により、バージョンがに変更されました$2a$。
$ 2x $、$ 2y $
2011年6月、bcryptのPHP実装であるcrypt_blowfishにバグが発見されました。8ビット目が設定された文字の扱いを間違えました。彼らは、システム管理者が既存のパスワードデータベースを更新し、に置き換え$2a$て$2x$、それらのハッシュが悪いことを示すことを提案しました(そして古い壊れたアルゴリズムを使用する必要があります)。彼らはまた、固定アルゴリズムによって生成されたハッシュに対してcrypt_blowfishを放出させるというアイデアを提案しました$2y$。
正規のOpenBSDを含め、他の誰も2x / 2yのアイデアを採用しませんでした。このバージョンマーカーの変更は、crypt_blowfishに限定されていました。
20億ドル
bcryptのOpenBSD実装にバグが発見されました。文字列の長さをunsignedchar(つまり、 8ビットByte)に格納していました。パスワードが255文字より長い場合、パスワードはオーバーフローして255で折り返されます。
bcryptはOpenBSD用に作成されました。ライブラリにバグがあったとき、彼らはバージョン番号を上げることにしました。

アルゴリズム
bcryptのアルゴリズムは、テキストの暗号化の結果である「OrpheanBeholderScryDoubt」使用して64回フグを。bcryptでは、通常のBlowfishキー設定機能が高価なキー設定(EksBlowfishSetup)機能に置き換えられています。
関数bcrypt 入力:
コスト:数値(4..31)
ログ2(反復)。例:12 ==> 2 12 = 4,096回の繰り返し
salt:バイトの配列(16バイト)
ランダムソルト
パスワード:バイトの配列(1..72バイト)
UTF-8でエンコードされたパスワード 出力:
ハッシュ:バイトの配列(24バイト) 高価なキー設定アルゴリズムと//初期化フグ状態 18のサブキーのアレイ(UInt32型):// P // S:フォー換字ボックス(Sボックス)、S 0 … S 3。各Sボックスは1,024バイト(UInt32 ) P、S EksBlowfishSetup(コスト、ソルト、パスワード)
//テキスト「OrpheanBeholderScryDoubt」を64回繰り返し暗号化 ctext 「OrpheanBeholderScryDoubt」 // 24バイト==> 3つの64ビットブロックを 繰り返す(64)
ctext EncryptECB(P、S、ctext)// ECBで標準のBlowfishを使用して暗号化モード // 24バイトのctextは、パスワードハッシュを 返しますreturn Concatenate(cost、salt、ctext)

高価なキーの設定
bcryptアルゴリズムは、次のように実行される「Eksblowfish」キーセットアップアルゴリズムに大きく依存しています。
関数EksBlowfishSetup 入力:
パスワード:バイトの配列(1..72バイト) UTF-8でエンコードされたパスワード
ソルト:バイトの配列(16バイト)
ランダムソルト
コスト:数値(4..31)
ログ2(反復)。例:12 ==> 2 12 = 4,096回の反復 出力: P: ラウンドごとの18個のサブキーのUInt32配列の配列
S 1 ..S 4: 4つのSBoxのUInt32
配列の配列。各SBoxは256UInt32です(つまり、各SBoxは1 KiBです) // P(サブキー)とS(置換ボックス)をpi P、S InitialState()の16進数で初期化します //パスワードとソルトに基づいてPとSを並べ替えます
P、S ExpandKey(P、S、ソルト、パスワード) //これは「高価なキー設定」の「高価な」部分です。 //それ以外の点では、キーの設定はBlowfishと同じです。 繰り返し(2コスト)
P、S ExpandKey(P、S、0、パスワード)
P、S ExpandKey(P、S、0、ソルト) P、 Sを返す
InitialStateは、元のBlowfishアルゴリズムと同じように機能し、P配列とSボックスのエントリにの小数部分を入力します。 π { pi}

  16進数で。

キーを展開
ExpandKey関数は次のことを行います。
関数ExpandKey 入力:
パスワード:バイトの配列(1..72バイト) UTF-8でエンコードされたパスワード
ソルト:バイト
ランダムソルト
P:UInt32の 配列18個のサブキーの配列
S 1 ..S 4:UInt32
4 1 KB SBox 出力:
P:UInt32の 配列ラウンドごとの18個のサブキーの配列
S 1 ..S 4:UInt32
4つの1KBSBox
Pサブキー配列に//ミックスパスワード のための N 1に対して18ない
P N P N XOR パスワード[32(N-1).. 32N-1] //は、環状としてパスワードを治療 // 128ビットのソルトを2つの64ビットの半分(Blowfishブロックサイズ)として扱います。 saltHalf salt //下位64ビットの saltSaltHalf salt //上位64ビットのsalt //すべてゼロで8バイト(64ビット)のバッファを初期化します。 ブロック0 P-ボックスに//ミックス内部状態
用の N 1へ9行う
// XOR 64ビットブロック、64ビットの塩半体と
ブロックブロックXOR saltHalf との間の//各繰り返し交互にsaltHalf 、およびsaltHalf
現在の鍵スケジュール用い//暗号化ブロック
のブロック暗号化(P、S、ブロック)
Pの2N ブロック
//の下位32ビットブロック
Pの2N + 1つのブロック //上位32ビットブロック //ミックスの内部Sボックスに状態を暗号化状態 のために I 1に4行う
ため のn 0へ127行う
ブロック暗号化(状態、ブロックの 排他的論理和 塩[64(N-1).. 64N-1])//上記のように
S iがブロック //下位32ビット
S I ブロック //上位32ビットが 戻り 状態
したがって、ソルト値がすべてゼロのすべてのXORは無効であるため、通常のBlowfishキースケジュールと同じです。似ていますが、128ビットキーとしてソルトを使用します。ExpandKey(state, 0, key)ExpandKey(state, 0, salt)

ユーザー入力
bcryptの多くの実装は、OpenBSDの実装に続いて、パスワードを最初の72バイトに切り捨てます。
数学的アルゴリズム自体は、18個の32ビットサブキー(72オクテット/バイトに相当)で初期化する必要がbcryptの元の仕様では、テキストベースのパスワードをユーザーランドからアルゴリズムの数値にマッピングするための特定の方法は義務付けられ本文中の1つの簡単なコメントは、文字列のASCIIエンコード値を単純に使用する可能性について言及していますが、必須ではありません。 56バイト(キーがASCII文字列の場合の終了ゼロバイトを含む)。」
上記の引用は、アルゴリズム自体が72バイトの初期値を使用している場合でも、「最大56バイト」のパスワードに言及していることに注意してプロボス氏とMazièresが短く制限の理由を述べていないが、それらはからの次の文が動機とされている可能性がブルース・シュナイアーフグののオリジナル仕様、「キーサイズ性を保証上の448 の制限すべてのサブキーのすべてのビットは、キーのすべてのビットに依存します。」
パスワードを初期数値に変換する方法はさまざまで、ASCII以外の文字を含むパスワードの強度が低下することも

批判

パスワードの最大長
bcryptのパスワードの最大長は72バイトです。この最大値は、パスワードを使用して18個の4バイトサブキー(P)を使用するExpandKey関数の最初の操作に由来しxor’sます。
P 1 ..P 18 P 1 ..P 18 XOR passwordBytes
パスワード(UTF-8でエンコードされている)は、72バイトの長さになるまで繰り返されます。たとえば、次のパスワード:
correct horse battery staple␀(29バイト)
ラウンドごとの18Pサブキーの72バイトと一致するまで繰り返されます。
correct horse battery staple␀correct horse battery staple␀correct horse(72バイト)
これは、パスワードがUTF-8でエンコードされた72バイトより長い場合、パスワードが切り捨てられることも意味します。一部の文字は、UTF-8でエンコードするときに4バイトを必要とする場合がこれは、最悪の場合、パスワードを18文字に制限できることを意味します。
(18文字、72バイト)
この72バイトのパスワードの制限(18個のサブキー*それぞれ4バイト)は、いくつかの方法で対処できた可能性が

解決策1-サブキーの数を増やす
使用するPサブキーの数を増やすことができるため、使用可能なパスワードの最大長を増やすことができます。Blowfishの原作者であるBruceSchneierは、ラウンドを追加することで遊ぶことができると述べました。これにはより多くのサブキーが必要であり、bcryptの場合はパスワードの最大長が長くなります。これの欠点は、最大長がないのではなく、パスワードの最大長がまだあることです。

解決策2-キーバイトをPサブキー配列にxorミックスし続けます
混合パスワードのみP限り続け1 … P 18。あなたが達したらP 18を、あなたはまだパスワードが未処理のバイトを持って、上のXORプロセスを続行P 1を。このアプローチの欠点は、計算時間がパスワードの長さをリークすることです(サイドチャネル情報のリーク)。

解決策3-ハッシュ前のパスワード
長いパスワードは、別の暗号化ハッシュ関数で事前にハッシュすることができます。この関数は常に固定サイズのダイジェストを出力します。結果のダイジェストが72バイト未満である限り、カットオフせずにbcryptにフィードできます。これは、Dropbox などが採用しているアプローチです。たとえば、次のパスワードについて考えてみます。
ਤੇਜ਼ ਭੂਰੇ ਲੂੰਬੜ ਨੇ ਆਲਸੀ ਕੁੱਤੇ ਉੱਤੇ ਛਾਲ ਮਾਰ ਦਿੱਤੀ(32文字、126バイト)
SHA-256を使用してこのパスワードをハッシュすると、256ビット(32バイト)のダイジェストが生成されます。
A7 B2 AA 86 CB 57 D3 08 EA 54 9F 34 E5 91 7E 8C 06 9B D0 0D 34 28 B1 CA 8D 71 B2 2E 84 DA C0 F8
ダイジェストをエンコードするBase64は、一貫して44文字の文字列を提供します。
p7KqhstX0wjqVJ805ZF+jAab0A00KLHKjXGyLoTawPg=(44文字、44バイト)
常に72バイトのbcrypt制限に適合します。
これは、bcryptのキャッシュハードな進化形であるPufferfish2で使用されるアプローチに似ており、HMACSHA -512を使用してパスワードを固定長の64バイト(512ビット)キーに変換します。

パスワードハッシュの切り捨て
bcryptアルゴリズムには、24バイトのテキストを繰り返し暗号化することが含まれます。 OrpheanBeholderScryDoubt (24バイト)
これにより、24バイトの暗号文が生成されます。例:
85 20 af 9f 03 3d b3 8c 08 5f d2 5e 2d aa 5e 84 a2 b9 61 d2 f1 29 c9 a4(24バイト)
次に、基数64を32文字にエンコードする必要が hSCvnwM9s4wIX9JeLapehKK5YdLxKcmk (32文字)
しかし、正規のOpenBSD実装は、パスワードハッシュを23バイトに切り捨てます。
85 20 af 9f 03 3d b3 8c 08 5f d2 5e 2d aa 5e 84 a2 b9 61 d2 f1 29 c9 a4 (23バイト)
結果として得られるbase-64でエンコードされたテキスト。通常は次のようになります。
hSCvnwM9s4wIX9JeLapehKK5YdLxKck =
末尾の=が削除され、ハッシュは次のようになります。 hSCvnwM9s4wIX9JeLapehKK5YdLxKck 正規の実装が結果のパスワードハッシュから8ビットを削除する理由は不明です。

非標準のbase64エンコーディングの使用
Base64で正規OpenBSDの実装によって使用される符号化は、ほぼすべての言語およびプラットフォームで使用可能な異なる符号化辞書を使用します。エンコーディングはcryptと互換性がこれは、エンコーディングがRFC4648と互換性がないことを意味します。

も参照してください
image
 無料のオープンソースソフトウェアポータル
bcryptは、2002年に開発されたBlowfishを実装するクロスプラットフォームのファイル暗号化ユーティリティの名前でも
Argon2(2015年にパスワードハッシュコンペティションによって選択されたアルゴリズム)
Crypt(C)#Blowfishベースのスキームcrypt –パスワードの保存と検証スキーム– Blowfish
キーストレッチ
PBKDF2(パスワードベースの鍵導出関数2) scrypt PufferFishは、改良されたbcrypt設計に基づくキャッシュハードパスワードハッシュ関数です。

参考文献
^ Provos、Niels; マジエール、デビッド; タランジェイソンサットン2012(1999)。「将来適応可能なパスワードスキーム」。1999 USENIX年次技術会議の議事録:81–92。
^ 「リポジトリへの最初の作業のコミット」。1997年2月13日。
^ 「SUSEセキュリティアナウンス:(SUSE-SA:2011:035)」。SUSEのcrypt()実装は、blowfishパスワードハッシュ関数(id $ 2a)をサポートしており、システムログインもデフォルトでこのメソッドを使用します。
^ ホイットロック、デビッド「BcryptElixir:Elixirのbcryptパスワードハッシュアルゴリズム」。GitHub。リバーラン。
^ 「パッケージbcrypt」。godoc.org。
^ 「jBCrypt-Java用の強力なパスワードハッシュ」。www.mindrot.org 。
^ 「bcrypt-bcryptパスワードハッシュ関数のJavaスタンドアロン実装」。github.com 。
^ 「bcryptjs」。npm。
^ スタッフ、ドナルド「bcrypt:ソフトウェアとサーバーの最新のパスワードハッシュ」–PyPI経由。
^ 「Re:CVEリクエスト:crypt_blowfish8ビット文字の誤処理」。2xと2yの起源であるoss-secに投稿して次の投稿も参照して
^ 「モジュラー暗号フォーマット」。Passlibv1.7.4ドキュメント。
^ “”passlib.hash.bcrypt-BCrypt””。Passlibv1.7.4ドキュメント。
^ 「ソフトウェアとサーバーの最新の(-ish)パスワードハッシュ:pyca / bcrypt」。2019年11月18日–GitHub経由。
^ “”GitHub –bcgit / bc-java:Bouncy Castle Java Distribution(Mirror)””。2019年11月18日–GitHub経由。
^ 「モジュラー暗号フォーマット— Passlibv1.7.1ドキュメント」。passlib.readthedocs.io。
^ “”bcryptパスワードハッシュのバグが修正され、バージョンの変更と結果””。undeadly.org。
^ デザイナー、ソーラー。「oss-sec:CVEリクエスト:crypt_blowfish8ビット文字の誤処理」。seclists.org。
^ ” ‘ bcryptバージョンの変更’ -MARC”。marc.info。
^ シュナイアー、ブルース(1994)。「高速ソフトウェア暗号化、新しい可変長キーの説明、64ビットブロック暗号(Blowfish)」。ケンブリッジセキュリティワークショップ議事録(1993年12月)。Springer-Verlag:191–204。
^ 「jBCryptセキュリティアドバイザリ」。
そして
「PHP5.3.7でのCRYPT_BLOWFISHの変更」。php.net。
^ 「セキュリティのシュナイアー:Blowfish暗号化アルゴリズム」。
^ 「Dropboxがパスワードを安全に保存する方法」。
^ 「Bcryptプロトコル…は一種の混乱です」。
^ http: //bcrypt.sourceforge.netbcryptファイル暗号化プログラムのホームページ
^ 「Android用bcryptAPK-DroidInformerで無料ダウンロード」。droidinformer.org。
^ 「T2パッケージ-トランク-bcrypt-ファイルを暗号化するユーティリティ」。t2sde.org。
^ 「OracleGoldenGateのライセンス」。docs.oracle.com。

外部リンク
crypt_blowfish、Openwallによって維持されている実装”