新しいパスワードを保存するためのランダムなフグの塩を生成するために、次のコードを実行する必要があると仮定します。
$blowfishCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
$type = '2a';
$cost = '08';
$maxIndex = strlen($blowfishCharacters) - 1;
for ($i = 0; $i < 22; $i++) {
$salt .= $blowfishCharacters[mt_Rand(0, $maxIndex)];
}
$salt = '$' . $type . '$' . $cost . '$' . $salt;
$pass = crypt($password, $salt);
私はこのトピックに関するいくつかの議論を読みましたが、それらはすべて異なる結果に至りました。 mt_Randは常に優れているようですが、この目的に適していますか?
ソルトは完全にランダムである必要はなく、ユーザーごとに一意である必要があります。詳細については、Crypto.SEの この質問 を参照してください。そのため、一部のWebサイトはユーザー名を使用してソルトを派生させます(つまり、_$salt=$username.$signup_date
_)。
あなたの場合、cryptが 'blowfish hash'と言うとき、それは本当に bcrypt を意味するので、- keepムーアの法則に合わせて コスト係数を選択するとき。
私があなたのコードで行ったいくつかの観察があります。まず、 strlen()
の最後にNULL文字が含まれないため、strlen($blowfishCharacters) - 1;
は、saltに_/
_が表示されないようにします。配列を構築するときは range()
を使用することもお勧めしますが、それは私の個人的な好みです。ホイールの再発明はしたくないので、ループを完全になくすこともできます(右?)。したがって、コードは次のようになります。
_$salt=array_merge(range('a', 'z'), range('A', 'Z'), ['.', '/']); //generate the dictionary
shuffle($salt);
$salt=array_slice($salt, 0, 21); //cut to size
_
これは、21個の要素を持つ_$salt
_配列を返します。 crypt
が必要とする22番目の要素 実際には区切り文字_$
_ です。
元の質問に答えるには mt_Rand()
のmanページ によると
デフォルトでは、PHPは、Rand()関数でlibc乱数ジェネレータを使用します。mt_Rand()関数は、これのドロップイン置換です。これは、既知の特性を持つ乱数ジェネレータを使用します。 "Mersenne Twister は、平均的なlibc Rand()が提供するものより4倍速く乱数を生成します。
そのため、「安全」ではなく、実行速度が速くなります。
結論として、あなたは塩を導出するために暗号グレードのPRFを必要としない。これは、ソルトが事前に計算されたハッシュテーブルを保護するためです。ソルトがない場合、攻撃者はテーブルを事前に生成し、データベース全体と比較して一致を見つけることができます。ソルトは、攻撃者がデータベース内でそのプロセス各エントリに対してを実行する必要があることを確認します。したがって、十分に高いコスト係数で攻撃を非常に高価にします。
もちろん、コストtooを高く設定すると、多数のユーザーが同時にログインしようとするとサーバーが苦労しますが、私はいつでもセキュリティの不便さのリスクを犠牲にしています。
だからあなたの質問への答えは はい。mt_Rand()
で十分です
編集:この記事 はbcryptの衛生に関する優れたガイドです。引用セクション#2、
完璧なソースは/ dev/urandomです。他のソースは、MCRYPT_DEV_URANDOMと組み合わせた場合、mcrypt_create_ivになります。どちらも使用できない場合は、openssl_random_pseudo_bytesまたはmt_Rand(最後の手段として)にフォールバックできます。
そうuse _mcrypt_create_iv
_ 代わりに.
ほとんどの状況では、ソルトは一意である必要があり、暗号的に予測できないものではありません。
したがって、その場合は、RNGが適切にシードされている限り、はい。塩の品質を改善するためのもう1つの一般的な手法は、現在の時刻に乱数を連結し、それをハッシュし(たとえば、SHA1)、テキストでエンコードし(たとえば、base64)、最初のもの[〜#〜 ] n [〜#〜]文字。そこでの衝突の可能性はかなりスリムです。
説明を編集
これが、このテクニックの内容とその理由の説明です。