パスワードのハッシュ化の仕組みを図解で説明 〜ソルトとストレッチング〜

Webサービスが、あなたのパスワードをどうやって保存しているか説明できますか?

パスワードを忘れた時、多くのサービスでは元のパスワードを教えてもらえず、新しいパスワードの再設定になります。

これは、サービス側も元のパスワードを持っていないためです。

パスワードを安全に保存する「ハッシュ化」の仕組みについて、図を使って説明していきます。

パスワードの保存の図。入力したパスワードをハッシュ関数でハッシュ値に変換し、データベースにはハッシュ値だけを保存する

パスワードをそのまま保存すると危ない

パスワードをそのままデータベースに保存していると、データベースの中身が流出した時に、全員のパスワードがそのまま知られてしまいます。

同じパスワードを他のサービスでも使っている人は、そちらにも不正にログインされる恐れがあります。

そこで、パスワードは 元に戻せない形に変換してから保存 します。

この変換に使うのがハッシュ関数です。

ハッシュ化とは?

ハッシュ関数は、データから決まった長さの値を計算する仕組み です。

計算された値を「ハッシュ値」といいます。

ハッシュ関数には、次のような特徴があります。

  • 同じデータからは、必ず同じハッシュ値ができる
  • データが少しでも変わると、ハッシュ値は大きく変わる
  • ハッシュ値から元のデータを計算することは困難

パスワードをハッシュ値に変換して保存することを、パスワードのハッシュ化といいます。

ログインの時はハッシュ値どうしを比べる

元のパスワードを保存していないのに、どうやってログインの確認をするのでしょうか。

ログインの時は、入力されたパスワードも同じ方法でハッシュ値にして、保存しているハッシュ値と比べます。

ログインの流れの図。入力されたパスワードからハッシュ値を計算し、保存しているハッシュ値と比べて、一致すればログインできる

① 利用者がパスワードを入力する

② サーバが、入力されたパスワードからハッシュ値を計算する

③ 保存しているハッシュ値と比べる

④ 一致すればログインできる

同じパスワードなら同じハッシュ値になる という特徴を使っています。

暗号化との違い

ハッシュ化と暗号化は、どちらもデータを読めない形に変換します。

違いは、元に戻せるかどうかです。

項目暗号化ハッシュ化
元に戻せるか鍵を使えば戻せる戻せない
鍵使う使わない
主な用途通信やファイルの保護パスワードの保存、改ざんの検知

暗号化は、鍵が盗まれると元のパスワードに戻されてしまいます。

パスワードの保存には、元に戻す必要がないハッシュ化が向いています。

ハッシュ化だけでは足りない理由

ハッシュ値から元のパスワードを直接計算することは困難です。

しかし、攻撃者はハッシュ値が流出すると、別の方法でパスワードを調べようとします。

よく使われるパスワードを片っ端からハッシュ値にして、流出したハッシュ値と一致するものを探す方法です。

さらに、よく使われるパスワードとハッシュ値の組み合わせを、事前に大量に計算しておく方法もあります。

これをレインボーテーブルといいます。

また、ハッシュ化しただけだと、同じパスワードの人は同じハッシュ値になる ため、1つ分かると同じパスワードの人がまとめて分かってしまいます。

そこで使われるのが、ソルトとストレッチングです。

ソルト

ソルトは、利用者ごとに作るランダムな文字列 です。

パスワードにソルトを付け加えてから、ハッシュ値を計算します。

ソルトの例の表。同じパスワードでも、ソルトなしでは同じハッシュ値、ソルトありでは違うハッシュ値になる

同じパスワードでも、ソルトが違うのでハッシュ値も違う値になります。

そのため、事前に計算しておいた表がそのままでは使えなくなります。

ソルトはハッシュ値と一緒にデータベースに保存します。

ソルト自体は秘密の値ではありませんが、利用者ごとに違う値にすることが大切です。

ストレッチング

ストレッチングは、ハッシュ値の計算を何回も繰り返す ことです。

ストレッチングの図。パスワードとソルトからハッシュの計算を何万回、何十万回と繰り返し、攻撃者が大量に試す時間を増やす

1回の計算では一瞬で終わるので、攻撃者は大量のパスワードを短い時間で試せてしまいます。

計算を何万回、何十万回と繰り返すと、1つのパスワードを確かめる時間が長くなります。

ログインする利用者には気にならない程度の時間でも、大量に試す攻撃者には大きな負担になります。

実際にはパスワード用の方式を使う

実際の開発では、ソルトとストレッチングを自分で組み立てるのではなく、パスワードの保存のために作られた方式を使います。

代表的なものに、bcrypt、scrypt、Argon2、PBKDF2があります。

MD5やSHA-256のような一般的なハッシュ関数は、計算が速いため、そのままパスワードの保存に使うのは向いていません。

開発で使う言語やフレームワークには、これらの方式を使う機能が用意されていることが多いので、まずはそれを使いましょう。

パスワードの保存方法の比較表。そのまま保存、ハッシュ化だけ、ソルトを追加、パスワード用の方式を比べている

まとめ

今回はパスワードのハッシュ化の仕組みについて説明しました。

パスワードは、元に戻せないハッシュ値にして保存します。

ハッシュ化だけでは足りないので、ソルトで利用者ごとに値を変え、ストレッチングで計算に時間をかけます。

元のパスワードを教えてもらえず再設定になるのは、サービスが元のパスワードを保存せず、ハッシュ値で保存しているからだと覚えておきましょう。

ハッシュ関数を使った改ざんの検知については、デジタル署名の仕組みを図解で説明の記事で説明しています。

鍵を使って元に戻す暗号化については、共通鍵暗号と公開鍵暗号の違いを図解で説明の記事で説明しています。

ログインの仕組みに関わる認証と認可の違いについては、認証と認可・OAuthの仕組みを図解で説明の記事で説明しています。