あなたが最初に遭遇すると思われる (そしてそれは大きな問題です) 問題は、データベースにパスワード ハッシュ関数がないことです。確かに、おそらく MD5() と SHA1() がありますが、これらは暗号化ハッシュ関数です。bcrypt() または scrypt() または PBKDF2() はありますか?
パスワード ハッシュ関数ではなく暗号化ハッシュ関数を使用すると、LinkedIn のパスワードが非常に迅速に解読される可能性があります。上記の関数のいずれかを使用しないと、ハッシュが漏洩した場合に同様に脆弱になります。
あなたのデータベースがパスワード ハッシュ アルゴリズムをサポートしていると仮定して、あなたの質問に答えていきます (単に 1 つを選択する必要があるため、bcrypt を使用します)。2 つの選択肢は次のとおりです。
データベースでのハッシュ:
$db->query("SELECT COUNT(*) FROM users WHERE username = '?' AND password = BCRYPT(?, (SELECT salt FROM user WHERE username = '?'))", $username, $password, $username);
if($row['count'] != 1)
{
// Not authenticated. Throw exception.
}
この場合、生のパスワードがデータベースに送信され、単純な yes または no (1 または 0) が返されます。このデータベース通信は暗号化できます。ハッシュとソルトがアプリケーションに保持されることはありません。
アプリケーションでのハッシュ:
$db->query("SELECT username, salt, password FROM users WHERE username = '?', $username);
if(bcrypt($password, $row['salt']) != $row['password'])
{
// Not authenticated. Throw exception.
}
この場合、ハッシュとソルトがデータベースからアプリケーションに取り込まれ、生のパスワードのハッシュと比較がそこで行われます。データベースへの通信は引き続き暗号化できます。生のパスワードがデータベース メモリに保持されることはありません。
効率のために、両方のハッシュ アルゴリズムが C (または何らかのコンパイル済み言語) で記述されており、OS によって提供される可能性があるため、同じ時間がかかると想定できます。アプリケーション ハッシュ オプションはネットワーク経由でより多くのデータを受信し、データベース ハッシュ オプションはより多くのデータを送信し、より複雑なクエリを持ちます (基本的に 2 つのクエリ、1 つはソルトを取得するため、もう 1 つは比較を行うため)。私がそのクエリを書いた方法でインデックスを使用することはできないかもしれませんが、クエリは書き直すことができます。どちらの場合も、データのサイズは 1 つの TCP パケットのままである可能性が高いため、速度の違いは無視できます。これは、サブクエリによるアプリケーション ハッシュ オプションの勝利と言えます。
露出用。生のパスワードは、ハッシュとソルトを合わせたものよりも機密性が高いと考えています。したがって、未加工のパスワードの公開を制限することがより安全な方法のように思われ、アプリケーションのハッシュ化がベスト プラクティスになります。