Webアプリケーションのユーザーが望めば、長いパスワードを使用できるようにしたいと思います。今日、私はbcryptのパスワードの長さの制限に気づきました(72文字、残りは切り捨て)。
私が次のことを行うことは安全ですか? PHPを使用しています。
現在の実装:
password_hash($password, PASSWORD_BCRYPT, $options);
問題の実装:
password_hash(hash('sha256', $password), PASSWORD_BCRYPT, $option);
問題の実装の欠点は何ですか?
私は暗号の専門家ではありません。アドバイスしてください。
問題の実装は、ユーザーが使用できるパスワードの長さを制限しますか?もしそうなら、限界は何ですか?
通常、これで問題ありません。これは、bcryptで任意の長さのパスワードを許可するかなり適切な方法です。
数学的には、2 ^ 256の可能な値がある64文字の文字列でbcryptを使用しています(SHA-256は256ビットの出力を提供しますが、これは通常64文字の16進数文字列として表されます)。誰かがSHA-256で一般的なパスワードを事前に計算したとしても、それらをbcryptで実行して、特定のハッシュの実際の入力が何であるかを見つける必要があります。
主な潜在的な欠点は実装の欠陥です。SHA-256値を保存すると、比較的高速に破壊されるため、攻撃者はbcrypt値を破壊するために労力を費やす必要はありません。
それでも、bcryptステップの反復回数を十分に高く保つことをお勧めします。これにより、処理時間に特に悪影響を及ぼすことはありませんが、ブルートフォース攻撃がはるかに困難になります。
一般的なケースについては、 パスワードの長さの制限を回避するためにbcryptを適用する前のハッシュ前のパスワード を参照してください。
提案された実装は安全です。ただし、関数の特別な使用法を文書化するように注意してください。
password_hash
は最初のNULLバイトでパスワードを切り捨てるため、hash
関数のオプション$raw_output=true
を使用しないでください。
それを行わないでください。あなたはあなたのキーの強さを、bcryptが単独で受け入れることができるものよりはるかに少なく制限しています。
代わりにこのアプローチを使用してください(疑似コードは有効なPHPではありません):
if length($password) > 72 bytes
then
$hash = sha256($password)
$password = concat(substring($password, 320 bits), base255encode($hash))
end if
bcrypt($password)
このようにして、256ビットと576ビットの間のパスワードは完全なエントロピーを保持し、576ビットを超えるパスワードはハッシュからの256ビットだけでなく、元のエントロピーをハッシュと一緒に使用できます。
ハッシュがパスワード全体で行われるべきか、それともハッシュが置換する320ビットを超える部分だけで行われるべきかは議論の余地があります。優れた特性を持つ暗号化ハッシュを選択した場合、それが違いを生むことを私は真剣に疑っています。
@ a-herseanが警告したように、base255encodeステップは、NULバイトがキーを早期に終了させることを回避します。