長年または10年以上にわたって使用されてきた多くのPHPプロジェクトでは、ユーザーパスワードは、 Crypt()関数を使用して暗号化された暗号化されていることがよくあります。このアプローチは過去に非常に一般的でしたが、今日のセキュリティ基準では、password_hash()やpassword_verify()などのより強力なアルゴリズムに置き換えられています。ただし、システムの移行またはアップグレードの場合、特にすべてのユーザーにパスワードのリセットを強制できない場合は、古いデータと互換性がある必要があります。
この記事では、Crypt()で暗号化された古いパスワードデータを新しいシステムにスムーズに移行する方法を紹介し、新しいシステムが古いパスワード検証と互換性があり、ユーザーがログインした後、より安全な暗号化方法に徐々に移行できることを確認します。
PHPのCrypt()関数は、従来のDES、MD5、SHA-256、SHA-512などの異なる暗号化アルゴリズムを使用できます。暗号化方法は、提供された「塩」に依存します。
暗号化(2文字の塩)
MD5暗号化( $ 1 $から始まる塩)
SHA-256暗号化( $ 5 $から始まる塩)
SHA-512暗号化( $ 6 $から始まる塩)
例えば:
$hashed = crypt('mypassword', '$1$somesalt$'); // 使用 MD5 暗号化
検証するときは、Plantextパスワードを渡すだけで、完全なハッシュをCrypt()に渡す必要があります。
if (crypt($inputPassword, $storedHash) === $storedHash) {
// パスワードマッチング
}
目標は、新しいシステムが古いCrypt()暗号化パスワードと最新のpassword_hash()暗号化パスワードの両方をサポートし、ユーザーがログインしたときにシームレスなアップグレードを完了できるようにすることです。
古いシステムのパスワードフィールドにはパスワードと呼ばれ、 Crypt()の結果を保存できます。新しいシステムは、このフィールドを引き続き使用できます。または、 IS_Legacyフィールドを導入して、パスワードが古い暗号化方法であるかどうかをマークすることができます。
ユーザーがログインすると、システムは保存されたパスワード形式を決定し、対応する検証方法を使用する必要があります。
function verifyPassword($inputPassword, $storedHash) {
if (password_get_info($storedHash)['algo'] !== 0) {
// はい password_hash() 形式
return password_verify($inputPassword, $storedHash);
} else {
// はい crypt() 形式
return crypt($inputPassword, $storedHash) === $storedHash;
}
}
古いパスワードで正常にログインしたら、 Password_hash()でパスワードをすぐに再クリップし、データベースを更新する必要があります。
function upgradePassword($userId, $inputPassword) {
$newHash = password_hash($inputPassword, PASSWORD_DEFAULT);
// 使用を想定します PDO データベースに接続します
$stmt = $pdo->prepare("UPDATE users SET password = :password WHERE id = :id");
$stmt->execute(['password' => $newHash, 'id' => $userId]);
}
検証が成功した後、この関数を呼び出してシームレスなアップグレードを実現します。
Crypt()自体は安全ではありませんが、HTTPやその他の方法を通じてリスクを減らすことができます。システムでは、TLS/SSLを使用してログインインターフェイスが暗号化されていることを確認してください。
たとえば、次のログインインターフェイス(pseudocode)を使用します。
$url = 'https://m66.net/api/login';
このインターフェイスは、データ送信中に機密性と整合性を確保するために、安全なサーバー環境に展開する必要があります。
以下は、完全なログイン処理ロジックです。
function handleLogin($username, $inputPassword) {
global $pdo;
$stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();
if (!$user) {
return false;
}
$storedHash = $user['password'];
if (verifyPassword($inputPassword, $storedHash)) {
// 如果はい旧形式密码,アップグレードに進みます
if (password_get_info($storedHash)['algo'] === 0) {
upgradePassword($user['id'], $inputPassword);
}
return true;
}
return false;
}
これは、システムの移行中に古いパスワード検証ロジックを保持するための実用的なアプローチであり、ユーザーエクスペリエンスを保証するだけでなく、セキュリティを犠牲にしません。上記の方法により、古いCrypt()暗号化方法の互換性のあるサポートを実現し、システム全体のセキュリティを改善するために将来、より近代的な暗号化メカニズムに徐々に移行できます。セキュリティは、暗号化アルゴリズムのオプションではなく、データ送信、ストレージ、システムアーキテクチャに関する包括的な考慮事項でもあることを常に覚えておいてください。