登録時のソルトの追加
つまり、<md5>によるハッシュ化は不可逆な処理であり、
ハッシュを入手したハッカーは、そのハッシュから
パスワードを得ることはできない、ということは
既にご存知ですね。
実はこの主張は完全には正しくありません。 現在、悪意あるハッカーたちは、 一般的な、そしてそれほど一般的ではないパスワードの ハッシュライブラリを作成しており、 どんな素人でも、単にそのハッシュを検索するだけで パスワードを解読できてしまうのです。
これは、十分に単純で一般的なパスワードについて の話です。
例えば、ハッシュ 827ccb0eea8a706c4c34a16891f84e7b
を検索してみてください。
Googleの検索結果にすぐに、これがパスワード
<'12345'>であると表示されるでしょう。
十分に複雑なパスワードのハッシュは、 この方法では解読できません(試してみてください)。
では、問題は何なのかとお聞きになるかもしれません。 私たち全員が複雑なパスワードで登録するようにすれば いいのではないか、と。 しかし、問題があります。大多数のユーザーは 自身のデータのセキュリティについて深く考えず、 非常に単純なパスワードを入力する可能性があるのです。
登録時に、例えば最小文字数を
<6>文字や<8>文字に制限するなどして、
より長いパスワードを考案するよう強制することはできます。
しかし、それでも<'123456'>や
<'12345678'>のようなパスワードは
出現してしまいます。
もちろん、パスワードの複雑さをチェックする より賢いアルゴリズムを考案することもできますが、 別の解決策があります。
その解決策の本質はこうです: パスワードに<ソルト>を加える必要があります。 ソルトとは、登録時にパスワードに追加される特別な ランダムな文字列です。 そして、ハッシュは単純なパスワードからではなく、 文字列「ソルト+パスワード」、つまりソルト済みの パスワードから計算されるようになります。
つまり、登録時には次のような処理を行います:
<?php
$salt = '1sJg3hfdf'; // ソルト - 複雑なランダム文字列
$password = md5($salt . $_POST['password']); // パスワードをソルト済みハッシュに変換
?>
この場合、ソルトはユーザーごとに異なり、 登録時にランダムに生成する必要があります。
これを行う完成した関数は以下の通りです:
<?php
function generateSalt()
{
$salt = '';
$saltLength = 8; // ソルトの長さ
for($i = 0; $i < $saltLength; $i++) {
$salt .= chr(mt_rand(33, 126)); // ASCIIテーブルからの文字
}
return $salt;
}
?>
この関数を使用して、コードを次のように書き換えることができます:
<?php
$salt = generateSalt(); // ソルト
$password = md5($salt . $_POST['password']); // ソルト済みパスワード
?>
繰り返しになりますが、これは登録時の変更です。 データベースには単なるパスワードのハッシュではなく、 ソルト済みパスワードのハッシュを保存します。
これだけではありません。
ユーザーテーブルには、
<login>フィールドと<password>フィールド
に加えて、<salt>フィールドも作成する必要があります。
このフィールドに各ユーザーのソルトを保存します。
上記のソルト済みパスワードを用いた登録を実装してください。