パスワードをデータベースに保存する際の暗号化の話【PHPでwebアプリ編】

password Webエンジニア

ユーザー登録の機能を作った「【PHPでwebアプリを作る】登録フォームでユーザーの新規登録をする」ではパスワードをそのままデータベースに格納しました。

しかしこれはやってはいけないことで、パスワードや個人情報は暗号化してデータベースに格納することはやっておく必要があります。

なぜ暗号化が必要なのか?

たくさんの情報漏洩のニュースがありますので既にご存じかもしれませんが、データベースに登録した内容というのは攻撃によって漏洩してしまう可能性がゼロではありません。

その時、パスワードを何の暗号化もせずそのまま平文で登録してしまっているとどんなことが起きてしまうでしょうか?

もし自分のサービスを使っている人がオンラインバンクのパスワードと同じパスワードを使っていたら、そのユーザーの口座にまで被害が及ぶ可能性があります。

自分のサービスでの話だけだからと楽観視することはできません。パスワードを暗号化して扱うことは必須の作業になってきます。

ハッシュ化との違い

今までさんざん暗号化と書いてきてしまったのですが、パスワードに対して行うことは実はハッシュ化というものです。

暗号化と何が違うのさ、ということですがハッシュ化は非可逆式、暗号化は可逆式です。

どういうことかというと、ハッシュ化はハッシュ化された後の文字列から、元の文字列に復元することはできません。なので不可逆になります。

そして暗号化は鍵などを使い、暗号化された文字列から元の文字列を復元できます。なので可逆式ということになります。

暗号化とハッシュ化の使い分け

元の文字列に戻して利用することのないものはハッシュ化で良いでしょう。ただその利用例は大方パスワードで利用することが多いのかなと思います。

他の住所や口座番号などの個人情報は、元の文字列に復元して利用することが前提になるので可逆の暗号化を行うことになるでしょう。

パスワードはハッシュ化なので、ハッシュ化の方法を掘り下げていきます。

ハッシュ化の方法

それでは具体的なハッシュ化の方法を見ていきましょう。これまでPHPでwebアプリを作ってきましたので、PHPでの例になります。

$password = 'abcd';
$password = password_hash($password, PASSWORD_BCRYPT);
echo $password;

これでパスワードabcdがハッシュ化され「$2y$10$ftEXSvKU0KjPNnkpeWH5p.NGS6sUouLtM0oPzmiYrlF3mNQHRrW6u」という文字列が表示されれば成功です。

これで100%絶対に安心!とまでは言い切れない実情もありますが、最低限安全にパスワードを運用はできるでしょう。

しかし次に問題になるのはログイン処理です。ユーザーはabcdと打ってくるのに、上のハッシュ化された文字と一致しているということはどう判断すればいいのか?それは以下になります。

$password = 'abcde';
$hash = '$2y$10$ftEXSvKU0KjPNnkpeWH5p.NGS6sUouLtM0oPzmiYrlF3mNQHRrW6u';
echo password_verify($password, $hash);

左側に入力されたパスワード、右側にハッシュ化した値でそれが一致するかを返してくれます。正しい場合は1、正しくない場合はNULLが返るようです。

判定は以下のようなif文で良いでしょう。

if (password_verify($password, $hash)) {
    echo '一致';
} else {
    echo '不一致';
}

試しに$passwordの中身を違う値に変えて不一致と表示されるかどうかを確認してみてください。

パスワードを使わない選択肢もある

企業でwebアプリを作成する際はパスワードをハッシュ化する技術は必須なので勉強がてらにやってみることは絶対に必須です。

しかし個人でwebアプリを作成して公開するくらいであればパスワードは持たないという選択肢を選ぶことも可能です。

よくwebアプリでツイッターアカウント利用する、やgoogleアカウントで利用する、というものがありますよね?

あれはそのwebアプリでアカウントを作成しなくても、他のwebアプリでのアカウント情報をそのまま認証に使えるという方式です。

OAuthという仕組みの実装になるので、各webアプリに合わせて少し実装は複雑にはなりますが、自分でアカウント情報は持たなくていいし、既にユーザーが他のアカウントを持っていれば利用もしやすくなります。

OAuthを利用した認証方法については少し複雑になってきてしまうので、また別記事で紹介いたします。