ハッシュ

任意のデータを固定長の値に変換する関数で、データの整合性検証や高速検索に使う

アルゴリズムセキュリティ
ハッシュ」の技術書を見る →

ハッシュとは

ハッシュは、任意のデータを固定長の値 (ハッシュ値) に変換する関数である。データの整合性検証、パスワードの保存、ハッシュテーブル (Map/Set) の高速検索に使われる。

ハッシュの特性

ハッシュ関数は、同じ入力に対して常に同じ出力を返す決定性を持つ。ハッシュ値から元のデータを現実的な計算量では復元できない一方向性、異なる入力が同じハッシュ値になりにくい衝突耐性、入力の 1 ビットの変化で出力が大きく変わる雪崩効果が特徴だ。

速度の要件は用途で正反対になる。整合性検証やハッシュテーブルでは大量のデータを捌くので速いほど良い。一方パスワード保存では、計算が速いほど攻撃者の総当たり試行も速くなるため、bcrypt や Argon2 のようにコストパラメータで意図的に計算を重くしたハッシュを使う。汎用の SHA-256 にパスワードをそのまま通す設計は避ける。

用途別のハッシュ関数

用途別のハッシュ関数を以下にまとめる。

用途ハッシュ関数
パスワード保存bcrypt, Argon2ユーザー認証
データ整合性SHA-256ファイルのチェックサム
ハッシュテーブルMurmurHashMap, Set の内部
コンテンツアドレスSHA-1, SHA-256Git のコミットハッシュ (既定は SHA-1)

パスワードのハッシュ

パスワードのハッシュのコード例を示す。

import { hash, compare } from 'bcrypt';

// 保存時: パスワードをハッシュ化
const hashed = await hash('password123', 10); // ソルト + ストレッチング

// 検証時: 入力とハッシュを比較
const isValid = await compare('password123', hashed); // true

SHA-256

SHA-256 のコード例を示す。

import { createHash } from 'crypto';

const hash = createHash('sha256').update('hello').digest('hex');
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

DynamoDB のパーティションキーとハッシュ

DynamoDB のパーティションキーとハッシュを図で示す。

パーティションキー: "user-123"
  ↓ 内部ハッシュ関数
ハッシュ値: 0x7A3B...
  ↓ ハッシュ値の範囲でパーティションを決定
パーティション B に格納

DynamoDB はパーティションキーをハッシュしてデータを分散する。均等に分散するキー設計が重要。

ハッシュの衝突

ハッシュの衝突を図で示す。

MD5("hello") = 5d41402abc4b2a76b9719d911017c592
MD5("world") = 7d793037a0760186574b0282f2f435e7
→ 入力の種類は無限だが出力は 128 ビット固定長なので、衝突は原理的に避けられない
→ 分かれ目は「衝突を攻撃者が狙って作れるか」

上の 2 例はハッシュ値が異なるが、入力の数が出力の組み合わせ数を上回る以上、同じ値に落ちる組はどこかに必ず存在する。実務で問題になるのは、その組を攻撃者が意図して作れるかどうかだ。MD5 は 2004 年に衝突の実例を示す論文が出て以降、生成コストが下がり続け、RFC 6151 (2011 年) は衝突耐性が必要な用途で MD5 はもはや受け入れられないと述べている。SHA-1 も 2017 年に、内容の異なる 2 つの PDF が同一のハッシュ値を持つ実例 (SHAttered) が公開された。整合性検証や署名では SHA-256 以降を選ぶ。逆に、攻撃者が入力を選べない重複検出やキャッシュキーのような用途で MD5 を使い続けることは誤りではない。

ハッシュ vs 暗号化

ハッシュと暗号化の違いを以下にまとめる。

観点ハッシュ暗号化
方向一方向 (復元不可)双方向 (復号可能)
用途検証、パスワードデータの秘匿
不要必要

実務での活用方法は関連書籍にも詳しい。

この記事は役に立ちましたか?

関連用語

関連する記事