ユーザー認証システムを構築する場合、パスワードの安全な取り扱いは、開発者が注意を払わなければならない問題です。パスワードを誤って比較すると、システムがタイミング攻撃などのセキュリティの脅威にさらされる可能性があります。 PHPは、パスワード検証を安全に処理するのに役立ついくつかの組み込み機能を提供します。その中で、 crypt()とhash_equals()の組み合わせは、比較的安全な練習方法です。
crypt()は、PHPの暗号化関数であり、いくつかのアルゴリズム( BCRYPT 、 SHA-512など)に基づいて暗号化パスワードをハッシュするために使用されます。その構文は次のとおりです。
string crypt(string $string, string $salt)
塩パラメーターは、暗号化アルゴリズムとその動作を決定します。最新のアプリケーションには、 BCRYPTが推奨され、適切な塩を次の方法で自動的に生成できます。
$salt = '$2y$10$' . substr(strtr(base64_encode(random_bytes(16)), '+', '.'), 0, 22);
$hash = crypt('mypassword', $salt);
多くの初心者が次のコードを書き、パスワードを確認します。
if (crypt($inputPassword, $storedHash) == $storedHash) {
// 正常にログインします
}
これは機能が実現可能に思えますが、深刻なセキュリティリスク -タイミング攻撃があります。攻撃者は、プログラムの応答時間のわずかな違いを測定することにより、正しいパスワードハッシュを徐々に推測できます。
タイミング攻撃の問題を解決するために、PHPは5.6からHash_equals()機能を提供し、2つのハッシュ値を安全に比較します。
bool hash_equals(string $known_string, string $user_string)
一定の時間アルゴリズムを使用し、文字列の内容に基づいて事前に戻りません。時間差の漏れを回避します。
<?php
// データベースから暗号化されたパスワードハッシュを取得するとします
$storedHash = '$2y$10$9YzyYtVht3tcGEn.7PiF2OlRM0HDTrM7Z5D.yPi8hdm0fJeFVKH4K'; // による crypt() 生成 bcrypt ハッシュ
$inputPassword = $_POST['password'] ?? '';
// 使用 crypt() 对使用户输入的密码进行ハッシュ,使使用存储ハッシュ作为 salt
$inputHash = crypt($inputPassword, $storedHash);
// 使使用 hash_equals() 安全比較
if (hash_equals($storedHash, $inputHash)) {
echo "正常にログインします!";
} else {
echo "エラーパスワード!";
}
?>
crypt()は依然として安全に使用できますが、PHPの公式は、アルゴリズムの選択とセキュリティの比較プロセスをカプセル化するため、 password_hash()とpassword_verify()を使用することをお勧めします。例えば:
// 创建密码ハッシュ
$hash = password_hash('mypassword', PASSWORD_BCRYPT);
// パスワードを確認します
if (password_verify($inputPassword, $hash)) {
echo "検証が合格しました";
}
ただし、一部のシナリオ(古いシステムの維持や特別なニーズなど)では、 crypt()とhash_equals()の組み合わせは、依然として許容可能で安全なソリューションです。
使用しないでください==または===パスワードのハッシュを比較します。
crypt()ハッシュパスワードを使用する場合、塩とアルゴリズムを正しく選択する必要があります(Bcryptを推奨)。
安全な比較には、タイミング攻撃を防ぐためにHash_equals()を使用します。
特定の理由がない場合は、低レベルのカプセル化の代わりにPassword_hash()およびpassword_verify()を使用することをお勧めします。
セキュリティはオプションではなく、ユーザーのパスワードを処理する際の要件です。正しいアプローチは、ユーザーのプライバシーを保護するだけでなく、システム全体の攻撃抵抗を改善することもできます。