結論: パスワードのハッシュ化とは、パスワードを、元に戻せない文字列に変えて保管する方法です。サービスの側は、パスワードそのものを持たず、ログインの時に、入力されたパスワードを同じ方法で変換して、保存した値と一致するかを確かめます。「復元できない」仕組みですが、弱いパスワードは、推測されることがあります。そこで、ソルトや、計算に時間のかかる方式で、推測をさらに難しくします。
ハッシュ化とは
ハッシュ化とは、データをハッシュ関数という計算にかけて、**決まった長さの文字列(ハッシュ値)**に変えることです。次のような性質があります。
| 性質 | 内容 |
|---|---|
| 同じ入力は、同じ結果になる | 同じパスワードなら、同じハッシュ値が得られる |
| 少し違うだけで、結果が大きく変わる | 1文字違うだけで、まったく別の値になる |
| 元に戻せない | ハッシュ値から、元のパスワードを計算で求めることは、できない |
たとえば、パスワード「sakura123」を、ハッシュ関数にかけると、意味のない長い文字列が出てきます。この文字列を見ても、元のパスワードは分かりません。
ログインの時に、何が起きているか
サービスは、パスワードそのものではなく、ハッシュ値を保管しています。
- 登録の時:パスワードをハッシュ化し、ハッシュ値だけをデータベースに保存する
- ログインの時:入力されたパスワードを、同じ方法でハッシュ化する
- 照合:保存したハッシュ値と、一致すれば、ログイン成功
この仕組みなら、万一、データベースが外部に出ても、パスワードが、そのまま見えるわけではありません。
暗号化との違い
ハッシュ化と暗号化は、混同されやすい言葉です。
| ハッシュ化 | 暗号化 | |
|---|---|---|
| 元に戻せるか | 戻せない | 鍵があれば、戻せる |
| 主な目的 | 一致するかの確認(パスワードの保管など) | 内容を隠して、あとで読む(通信・ファイルなど) |
| 例 | パスワードの保管 | HTTPS通信、ZIPのパスワード保護 |
パスワードの保管は、「あとで元の文字列を読む」必要がないため、元に戻せないハッシュ化が向いています。暗号化は、鍵が盗まれると、すべてが読まれてしまうためです。
「復元できない」のに、なぜ危険な場合があるのか
ハッシュ値から、計算で元に戻すことは、できません。しかし、攻撃者は、別の方法で、パスワードを当てにいきます。
- 総当たり攻撃:考えられるすべての文字列を、片っ端からハッシュ化して、一致するものを探す
- 辞書攻撃:よく使われるパスワードのリストを、ハッシュ化して、一致するものを探す
- 対応表を使った攻撃:あらかじめ計算しておいた、パスワードとハッシュ値の対応表(レインボーテーブルなど)で、探す
そのため、「ハッシュ化されていたから、絶対に安全」とは言えません。短い・単純なパスワードほど、見つけられやすくなります。流出した時の考え方は、ハッシュ化されたパスワードが流出したら?で解説しています。
推測を難しくする仕組み:ソルトとストレッチング
ソルト(salt)
ソルトは、パスワードに足す、ランダムな文字列です。ユーザーごとに別の値を使います。
- 同じパスワードでも、ソルトが違えば、ハッシュ値が変わる
- 「同じパスワードを使っている人」を、ハッシュ値の一致で見つけられなくなる
- あらかじめ作った、対応表を使った攻撃を、難しくする
ソルトは、ハッシュ値と一緒に、保管されるのが一般的です。秘密にするためのものではなく、使い回しを防ぐためのものです。
ストレッチング(計算を、わざと重くする)
ハッシュ化を、何度も繰り返すことで、1回の計算にかかる時間を、わざと長くします。正規のログインでは、1回の計算で済むため、ほとんど影響がありません。一方、数億回の総当たりをする攻撃者には、大きな負担になります。
パスワード向けの方式
ハッシュ関数には、いろいろな種類があります。計算が速いもの(MD5、SHA-1、SHA-256など)を、そのまま使うのは、パスワードの保管には向きません。 速いということは、総当たりも速くできる、ということだからです。
パスワードの保管には、ソルトを自動で扱い、計算の重さを調整できる方式が使われます。現在は、次のようなものが、よく挙げられます。
| 方式 | 特徴 |
|---|---|
| Argon2 | 新しい方式。メモリを多く使う設計で、専用機器による攻撃にも強いとされる |
| bcrypt | 広く使われている。ソルトを含めて扱える |
| scrypt | メモリを多く使う設計 |
| PBKDF2 | 標準的な方式。繰り返しの回数で、重さを調整する |
どの方式を使うかは、サービスの設計や、基準によって異なります。選定の際は、公式の推奨や、セキュリティの基準を確認します。
開発者向け:短いコードの例
Pythonのbcryptライブラリを使うと、ソルトの生成と、ハッシュ化を、まとめて行えます。
import bcrypt
password = "sakura123".encode("utf-8")
# 登録時:ソルトを自動で生成して、ハッシュ化する
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
# ログイン時:入力されたパスワードと、保存したハッシュ値を照合する
print(bcrypt.checkpw(password, hashed)) # True
このコードは、仕組みを説明するための例です。実際のサービスでは、設計・運用の基準に沿って、実装してください。