WEB業界で働く人や興味がある人に役立つ情報サイト“qam(カム)”

JQ

2021/03/17

【PHP】パスワードをデータベースに保存するときは、しっかり「ハッシュ化」をしよう

投稿者: JQ
カテゴリー: プログラム >PHP

パスワードはハッシュ化

会員制サイトのWebサイトを作成する場合は、ユーザ名とパスワードを入力させ、両者の組み合わせが正しい場合のみログインを承認するという仕組みが必要となります。

このユーザ名とパスワードは、通常はMySQLなどのデータベースに格納をしておくことになると思いますが、パスワードを平文(暗号化などを何も施さない素のままのテキスト)のままで格納していませんか?

この場合、仮にデータベースの内容が流出してしまうと、簡単にユーザ名とパスワードの組み合わせがわかってしまうので、非常にセキュリティ的に危険な状態です。

今回は、パスワードなどの秘匿性の高い情報を、仮に流出してしまっても悪用されにくい形に変える方法をご紹介します。

パスワードは「ハッシュ化」しよう

「ハッシュ化」とは?

パスワードをデータベースに保存する時に、最低限おこなうべきなのが「ハッシュ化」です。

ハッシュ化とは、元のデータから一定の計算手順に従ってハッシュ値と呼ばれる規則性のない固定長の値を求め、その値によって元のデータを置き換えること。
参照:ハッシュ化(ハッシング)とは – IT用語辞典 e-Words

簡単に言うと、例えば「password」という文字列を「$2y$10$6LwICMlH81FI8Omphn5g7uV9pjv/Iufu0lRlLDIUDF4YHndhDos4e」のように、見ただけでは元の文字列が何なのかわからないように変換をすることです。

user password
TaroYamada password
JiroYamada $2y$10$6LwICMlH81FI8Omphn5g7uV9pjv/Iufu0lRlLDIUDF4YHndhDos4e

このように「TaroYamada」のパスワードは見たままの「password」とすぐに分かってしまいますが、「JiroYamada」のパスワードはハッシュ化されているため、仮に覗かれてしまっても、どんな文字列がパスワードなのかを推測することが出来ません。

ハッシュ化には色々種類がある

PHPを使って文字列を「ハッシュ化」しようと思うと、色々な方法が考えられます。

md5()
$origin_txt = 'password';
$hashed_txt = md5($origin_txt);
var_dump($hashed_txt);
// 出力結果:string(32) "5f4dcc3b5aa765d61d8327deb882cf99"
sha1()
$origin_txt = 'password';
$hashed_txt = sha1($origin_txt);
var_dump($hashed_txt);
// 出力結果:string(40) "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"

以上のように、PHPにはハッシュ化をするためのメソッドがいくつか用意されていますが、上記2つのメソッドには問題点があります。

md5()やsha1()は、毎回同じハッシュ値を生成してしまう

上記でご紹介した2つのメソッドで生成されたハッシュ値は、元の文字列が同じなら、何度ハッシュ値を生成しても同じ値になってしまいます。
そのため、現在では使用することに対し、警告が出ています。

そこで、これらの問題点を解決する方法として「password_hash」というメソッドを使う方法があります。

安全なハッシュ化処理「password_hash」

PHPには「password_hash」というメソッドも用意されています。パスワードなどの情報をハッシュ化するときはこのメソッドを使用することを強くおすすめします。

この「password_hash」は、元にする文字列が同じでも、処理をするごとに異なった結果を返してくれるため、上記2つのメソッドよりも、元のパスワードを推測することがより困難(ほぼ不可能)になります。

$origin_txt01 = 'password';
$origin_txt02 = 'password';

$hashed_txt01 = password_hash($origin_txt01, PASSWORD_DEFAULT);
$hashed_txt02 = password_hash($origin_txt02, PASSWORD_DEFAULT);

var_dump($hashed_txt01);
var_dump($hashed_txt02);

// 出力結果:string(60) "$2y$10$vPnua7kjhyDBNBEPIMm9T.U0R16QeJbAx4piSWPR6aZAnolBivab."
// 出力結果:string(60) "$2y$10$0zifCJeJqE4NcsAX6Q.RJ.o.yHnXzrgcYhIVuRMYQ/kisJ7bpE52C"

パスワード照合に問題はないの?

ここで湧いてくる疑問として、「同じ文字列でも異なるハッシュ値になってしまうのに、ログインのときのパスワード照合に問題はないの?」ということです。

これに関しては、ハッシュ化前の文字列と、password_hashによってハッシュ化された文字列が同じものかどうかを確認するためのメソッド「password_verify」が用意されていますので、こちらを利用します。

$origin_txt = 'password';

$hashed_txt = password_hash($origin_txt, PASSWORD_DEFAULT);

var_dump(password_verify($origin_txt, $hashed_txt));

// 出力結果:bool(true)

このように、password_verifyを使えば、元の文字列とハッシュ化された文字列が同じものであればtrueを返してくれますので、if文の判定要素として使用することが出来ます。

まとめ

今回は、パスワードなどの秘匿性の高い情報をデータベースに格納する際に、平文で保存するのはとても危険で、必ずハッシュ化して文字列で格納するのが良い。
さらに、ハッシュ化する際にもよりセキュリティが強固な「password_hash」というメソッドを使うべきであるということをお伝えしました。

会員制のサイトを作成する際には、個人情報などの取り扱いは非常に慎重におこなうべきかと思いますので、今回ご紹介したような方法で、安全に情報を運用していきましょう。

最後までお読みいただき、ありがとうございました。

よろしければシェアしていただければ幸いです。

  • このエントリーをはてなブックマークに追加

関連記事

よろしければこちらの記事もお読みください。

WEB業界ならqam!qam(カム)はWEB業界で働く人や興味がある人に役立つ情報サイトです。
マーケティングやデザイン、マークアップ(コーディング)、プログラム、トレンドなどの情報をqamライター陣が執筆。噛めば噛むほど(読めば読むほど)制作・開発や運営・運用、業界知識やノウハウを学ぶことができます。

トップへ