パスワード暗号化にPHPのcrypt()関数を使用する場合、多くの開発者は奇妙な現象に気付くでしょう。暗号化の結果の長さは13文字、時には20、34などです。この長さの矛盾は、コードに何か問題があること、またはパスワードが切り捨てられたり暗号化されたりしないと誤って考えることができます。それで、何が起こっているのですか?
PHPのCrypt()関数はカプセル化された暗号化インターフェイスであり、基礎となるレイヤーはオペレーティングシステムによって提供される暗号化アルゴリズムに依存します。この関数の最初のパラメーターは暗号化される文字列で、2番目のパラメーターは「塩」です。この塩値は、暗号化の結果の一意性に影響するだけでなく、どの暗号化アルゴリズムが使用されるかを決定します。
echo crypt("mypassword", "salt");
塩値を与えない場合、または誤った形式を使用しない場合、PHPは従来のDES(データ暗号化標準)アルゴリズムなどの古い暗号化方法に自動的に戻ります。
crypt()関数は複数のアルゴリズムをサポートし、異なるアルゴリズムが塩値のプレフィックスによって決定されます。いくつかの一般的な塩値形式と、それらに対応する暗号化アルゴリズムを次に示します。
アルゴリズム | 塩値形式 | 結果の長さ |
---|---|---|
des | 2文字 | 13文字 |
MD5 | $ 1 $ ... | 34文字 |
ブローフィッシュ | $ 2A $ ... / $ 2Y $ ... | 60文字 |
SHA-256 | $ 5 $ ... | 43文字 |
SHA-512 | $ 6 $ ... | 86文字 |
したがって、プレフィックスされた塩値を明示的に通過させたり、非形式の塩値を渡さない場合、PHPは13文字のみを出力する古いdes暗号化の使用に戻る可能性があります。
例えば:
// 使用 SHA-512 暗号化
echo crypt("mypassword", '$6$rounds=5000$usesomesillystring$');
// 出力はに似ています:$6$rounds=5000$usesomesill...(総長さはおよそ86)
次のコードでは、デフォルトのDESアルゴリズムを使用します。
echo crypt("mypassword", 'sa');
// 出力はに似ています:sahGDf/YwKdl6(のみ13文字)
この問題を回避するために、常に明示的なプレフィックス、できれば生成されたランダム塩を使用して塩値を常に使用し、BlowFish( $ 2Y $ )やSHA-512( $ 6 $ )などのより安全なアルゴリズムを選択してください。
このような塩値を自動的に生成できます。
function generateSalt($algo = 'sha512') {
switch ($algo) {
case 'blowfish':
return '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(22))), 0, 22);
case 'sha256':
return '$5$' . bin2hex(random_bytes(6));
case 'sha512':
default:
return '$6$' . bin2hex(random_bytes(6));
}
}
$password = 'mypassword';
$salt = generateSalt('sha512');
$hash = crypt($password, $salt);
echo $hash;
<?php
function hashPassword($password) {
$salt = '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(22))), 0, 22);
return crypt($password, $salt);
}
$plainPassword = '123456';
$hashed = hashPassword($plainPassword);
// データベースに保存されたと仮定します
file_put_contents('/var/www/m66.net/passwords.txt', $hashed . PHP_EOL);
// パスワードを確認します
$inputPassword = '123456';
$isValid = crypt($inputPassword, $hashed) === $hashed;
echo $isValid ? 'パスワードを修正します' : 'エラーパスワード';
?>
Crypt()関数を使用する場合、結果の異なる長さの基本的な理由は、「塩値」の形式が暗号化アルゴリズムを決定することです。暗号化のセキュリティと一貫性を確保するには:
常に正しい形式の塩値で明示的に渡されます。
$ 2Y $または$ 6 $などの最新の安全なアルゴリズムを選択します。
デフォルトの動作や短い塩の形式に依存しないでください。
これらの根本的な詳細を理解した後、パスワード処理の隠されたセキュリティリスクを回避し、暗号化ロジックをより制御可能で信頼性を高めることができます。