Webアプリケーションのログインプロセスのベストプラクティスは、ハッシュされたパスワードをバイト配列として比較することです。このベストプラクティスの本当の理由は何ですか?誠実さについてですか?
Cert Secure Coding バイト配列の方が解放しやすいため、バイト配列の使用について説明しています。
ここにはいくつかの問題があります。最初のリンクは、リンクした Cert Secure Coding example とリンクされた StackOverflow answer の両方で参照されていますが、Daniel Groverのコメントからは、ハッシュの比較とは特に関係がありません。ユーザーが送信したパスワードと、以前に保存されたハッシュを使用しますが、入力パスワード自体を保存します。彼らが説明する問題は、Javaや.NETなどのプラットフォームでの文字列の不変性の1つです。つまり、クリアテキストのパスワードが文字列として保存されている場合、アプリケーションで削除できません。ただし、ガベージコレクタによってのみ行われるため、それが発生する前に発生するメモリダンプにより、クリアテキストのパスワードが漏洩する可能性があります。
ただし、パスワードハッシュを比較する場合、これは実際には問題になりません。文字列ではなくバイト配列を使用する理由は、セキュリティへの影響が少ないですが、それでも良い考えです。第1に、ハッシュ関数への入力とハッシュ関数からの出力は、通常バイトの形式であるためです。バイトを出し入れする場合、比較するために文字列に戻す変換はほとんど意味がありません。さらに、不正な文字列エンコーディングによって引き起こされる(セキュリティの脆弱性を含む)バグのクラス全体を排除します。たとえば、2つの完全に異なるパスワードを表す2つのバイト配列は、比較前にASCIIに誤って変換された場合、誤って同一と報告することがあります。多くの場合、基本的な128文字以外のバイトASCII範囲は同じ(3F)ASCII文字値に変換され、元のバイト配列がそうでなかった場合でも文字列の衝突の可能性を開きます。バイトをそのままにしておくと、この潜在的な脆弱性を完全に排除します。
したがって、それらを考えて、それらを何であるかで処理すると、文字列ではなくバイトのハッシュ出力により、コードがよりシンプルで正確になり、エラーが発生しにくくなります。セキュリティ上、これは良いことです。
ここでは、「ハッシュされたパスワードを比較する」という表現で、わずかに直交する2つの問題を混同しています。
パスワードの保存(ハッシュ化前)
Jon SkeetがSOで言うように:
文字列は不変です(Javaおよび他の多くのGC言語)。つまり、文字列を作成した後、別のプロセスがメモリをダンプできる場合、(リフレクションを除いて)方法はありませんガベージコレクションが開始される前にデータを削除します。
ユーザーのパスワードを処理する場合、このリスクから保護する必要があるため、一度使用したらすぐに上書きできるデータ型を使用します。バイトの配列は請求書に完全に適合します。パスワードハッシュアルゴリズムを適用したら、配列をゼロで埋めることができます(またはランダムデータなどを使用します)。
ハッシュの比較(つまり、ハッシュ後、ログイン前)
ハッシュ関数はバイトを出力します。これは、それらがどのように定義され、通常、ほとんどのプログラミング言語でどのように動作するかです。したがって、最初にコンバーターで実行することなく、2つのバイト文字列をそのまま比較するのが最も理にかなっています。
ただし、パスワードハッシュがデータベースでbase64でエンコードされている場合でも、計算されたパスワードハッシュを取得してbase64でエンコードし、文字列を比較してもセキュリティは失われません。ハッシュはすでにデータベースにあります-攻撃者がプロセスメモリをダンプするのに十分なシステムへのアクセス権を持っている場合、データベースからパスワードハッシュを回復するのはそれほど難しいことではありません-それを釣り出すかどうかは重要ではありませんそこで、またはGCが実行されるまで保持される不変のコピーから。
まとめ
だから物事をシンプルに保つために: