ハッシュ(Hash)とは、どんな長さのデータからでも、決まった長さの短い値を作り出す仕組み、またはそうして作られた値のことです。この値はハッシュ値やダイジェストと呼ばれ、元のデータが1文字でも違えば、まったく別の値になります。
現実世界に例えると、ハッシュは書類につけた指紋のようなものです。指紋どうしを見比べれば同じ書類かどうかを確かめられますが、指紋から書類の中身を読み取ることはできません。中身を明かさずに同一性だけを確かめられる点が、ハッシュの便利なところです。
暗号化との違い
| 項目 | ハッシュ | 暗号化 |
|---|---|---|
| 目的 | 同じものかを確かめる | 中身を人に見せない |
| 元に戻す | 戻せない | 鍵があれば戻せる |
| 出力の長さ | 常に一定 | 元の長さに応じて変わる |
| 主な使い道 | パスワード保存、改ざん検知 | 通信内容やファイルの保護 |
どちらもデータを別の姿に変える点は同じですが、暗号化は「あとで元に戻すこと」を前提にした仕組み、ハッシュは「戻さないこと」を前提にした仕組みです。目的がまったく違うため、置き換えて使うことはできません。
同じ入力からは必ず同じ値が出る
ハッシュの土台になる性質です。同じデータを何度計算しても、いつでも同じハッシュ値になります。パソコンが違っても、計算した日が違っても結果は変わりません。だからこそ、手元のファイルと配布元のファイルが同じものかどうかを、値を見比べるだけで判断できます。逆に値がひとつでも違えば、途中で中身が変わったと分かります。
元のデータには戻せない
もうひとつの重要な性質が一方向性です。ハッシュ値からは、計算のもとになったデータを求められません。長いデータを短い値に押し込める以上、情報の大部分は捨てられているためです。この「戻せなさ」は欠点ではなく、預かった値が漏れても元の中身までは知られない、という安全性の根拠になっています。
パスワードの保存に使われる
もっとも身近な使い道です。サービス側はパスワードそのものではなく、そのハッシュ値だけを保管します。ログイン時は入力された文字を同じ方法で計算し、保管してある値と一致するかを見ます。こうしておけば、万一データが流出しても、そこからパスワードを読み取ることはできません。実際には利用者ごとに違う文字列(ソルト)を混ぜて計算し、同じパスワードでも別の値になるようにします。
ファイルが壊れていないか確かめる
配布の場面でもよく使われます。ダウンロードページにSHA-256などの値が併記されているのは、受け取ったファイルが途中で壊れたり差し替えられたりしていないかを確かめてもらうためです。手元で同じ計算をして値が一致すれば、配布元が用意したものと同一だと判断できます。通信の途中で改ざんされた場合も、この照合で気づけます。
衝突という弱点
出力の長さが決まっている以上、異なるデータからたまたま同じハッシュ値が出てしまうことがあります。これを衝突と呼びます。実用上まず起きない確率に抑えるのが良いハッシュ関数の条件ですが、計算の弱点を突いて意図的に衝突を作り出す手口が見つかった方式もあります。安全性はハッシュ関数の設計しだいという点に注意が必要です。
古い方式は使わない
選び方には決まった答えがあります。MD5やSHA-1は衝突を作る方法が知られており、安全性が必要な用途ではもう使いません。現在はSHA-256をはじめとするSHA-2系が標準的で、パスワードの保存には計算にわざと時間をかける専用の方式が使われます。古い解説記事のとおりに実装すると、いまでは危険な選択になることがあります。
データを素早く探すためにも使う
安全性とは別の使い道もあります。データからハッシュ値を求め、それを住所代わりにして保管場所を決める「ハッシュテーブル」という仕組みです。端から順に探さなくても、値を計算した時点で置き場所が分かるため、大量のデータからでも一度で目的のものにたどり着けます。プログラムの連想配列や辞書型は、この考え方で作られています。

コメント