ハッシュ化とは
ハッシュ化を理解するうえで重要な3つの性質があります。
- 一方向性(Pre-image resistance): ハッシュ値から元のデータを逆算することが計算上困難です。
- 決定性(Determinism): 同じ入力に対しては必ず同じハッシュ値が出力されます。
- 衝突耐性(Collision resistance): 異なる2つの入力が同じハッシュ値を生成する「衝突」を見つけることが計算上困難です。
この3つの性質が成立するとき、ハッシュ関数はセキュリティ用途に使用できる暗号学的ハッシュ関数と呼ばれます。MD5・SHA-1は衝突耐性が破られており、現在は暗号学的ハッシュ関数としての使用は推奨されていません。
ハッシュ関数の仕組み
雪崩効果(Avalanche Effect)の実例
ハッシュ関数の重要な特性として「雪崩効果」があります。入力の1ビットが変わるだけで、出力のほぼ半分のビットが変化します。以下は hello と Hello(大文字のH)の比較です。
| 入力 | アルゴリズム | ハッシュ値 |
|---|---|---|
hello |
MD5 | 5d41402abc4b2a76b9719d911017c592 |
Hello |
MD5 | 8b1a9953c4611296a827abf8c47804d7 |
hello |
SHA-256 | 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 |
Hello |
SHA-256 | 185f8db32921bd46d35401562f194e34f5d6aaf2ff1a4a28529ef22f8f0e3b5a |
大文字・小文字という1文字の違いだけで、ハッシュ値は完全に別の値になっています。この特性により、データが少しでも改ざんされた場合に確実に検出できます。
MD5・SHA-1・SHA-256の比較
| アルゴリズム | ビット長 | 出力文字数 | 速度 | 安全性 | 推奨用途 |
|---|---|---|---|---|---|
| MD5 | 128 bit | 32文字 | 高速 | 衝突脆弱(非推奨) | チェックサム(簡易用途のみ) |
| SHA-1 | 160 bit | 40文字 | やや高速 | 衝突脆弱(廃止済) | レガシーシステムのみ(新規不可) |
| SHA-256 | 256 bit | 64文字 | 中速 | 現行推奨(安全) | 電子署名・証明書・ブロックチェーン |
| SHA-384 | 384 bit | 96文字 | 中速 | 安全 | 高セキュリティ要件の署名 |
| SHA-512 | 512 bit | 128文字 | 中速 | 安全 | 大容量データのダイジェスト |
MD5の脆弱性について
MD5は1992年に設計されましたが、2004年に研究者によって衝突攻撃が実証されました。異なる内容の2つのファイルに同じMD5ハッシュ値を意図的に生成することが可能になったため、デジタル署名やSSL証明書での使用は廃止されています。現在はファイル転送の簡易チェックサムなど、セキュリティ上の影響が低い用途に限って使われています。
SHA-1のSHAttered脆弱性
SHA-1は2017年にGoogleとCWIアムステルダムの研究チームが「SHAttered」と名付けた攻撃で、世界初のSHA-1衝突を実証しました。2つの異なるPDFファイルがまったく同一のSHA-1ハッシュ値を持つことが示されたのです。この結果を受け、Googleはブラウザ上でSHA-1を使用したSSL証明書の信頼を失効させ、NISTも正式にSHA-1の廃止を勧告しました。
SHA-256はなぜ安全か
SHA-256はNIST(米国国立標準技術研究所)が策定したSHA-2ファミリーの一員で、256ビットの出力長を持ちます。現時点では実用的な衝突攻撃は報告されておらず、TLS/SSL証明書・Bitcoin・コード署名・パスポートのデジタル認証など幅広い分野で採用されています。NISTは2030年以降もSHA-256の継続使用を承認しています。
主な用途
パスワード保存(ソルト+ハッシュ)
ユーザーのパスワードはデータベースに平文で保存してはいけません。ハッシュ化して保存することで、データベースが漏洩してもパスワード自体は保護されます。ただし、同じパスワードは同じハッシュ値になるため、ソルト(salt) と呼ばれるランダムな文字列をパスワードに付加してからハッシュ化します。これによりレインボーテーブル攻撃を無効化できます。
なお、SHA-256のような汎用ハッシュ関数は計算が高速すぎるため、パスワード保存には向きません。パスワード専用に低速設計された bcrypt・Argon2・scrypt を使用するのがベストプラクティスです。
ファイル整合性チェック(ダウンロード検証)
ソフトウェアの配布サイトでは、ダウンロードファイルのSHA-256ハッシュ値を公開しています。ダウンロード後にハッシュ値を計算して公開値と比較することで、転送中の改ざんや破損を検出できます。
デジタル署名・SSL/TLS証明書
電子署名では、署名対象のデータをハッシュ化し、そのハッシュ値を秘密鍵で暗号化します。受信者は公開鍵で復号してハッシュ値を取り出し、受け取ったデータのハッシュ値と照合することで正当性を検証します。現在の証明書はSHA-256が標準です。
ブロックチェーン
BitcoinはSHA-256をマイニング(Proof of Work)とトランザクション検証に使用しています。各ブロックには直前ブロックのハッシュ値が含まれており、チェーン全体の改ざん検知を実現しています。
Gitのコミットハッシュ
Gitはコミット・ツリー・ファイルオブジェクトの識別にSHA-1(旧来)またはSHA-256(SHA-256リポジトリ形式)を使用しています。コミットハッシュはリポジトリ内で内容を一意に識別するIDとして機能します。
ハッシュ生成ツールの使い方
-
テキストを入力する
ハッシュ生成ツールを開き、入力欄にハッシュ化したいテキストを入力または貼り付けます。 -
ハッシュ生成ボタンを押す
「ハッシュ生成」ボタンをクリックすると、MD5・SHA-1・SHA-256・SHA-384・SHA-512の5種類のハッシュ値が同時に計算されて表示されます。 -
結果をコピーして利用する
各アルゴリズム行の「コピー」ボタンを押すと、ハッシュ値がクリップボードにコピーされます。ファイル検証や比較に活用できます。 - 用途別のアルゴリズムを選定する — ファイルチェックサムは SHA-256、レガシー互換は MD5、高エントロピー要件は SHA-512。セキュリティ用途で MD5 / SHA-1 は新規採用不可。
- 公開値と突き合わせて整合性検証する — GitHub Releases や OS 配布サイトの公開 SHA-256 値と、ダウンロードしたファイルの再ハッシュ結果を見比べて、改竄や転送エラーの有無を確認します。
ハッシュ化・暗号化・エンコードの違い
| 項目 | ハッシュ化 | 暗号化 | エンコード |
|---|---|---|---|
| 可逆性 | 不可逆(元に戻せない) | 可逆(鍵で復号可能) | 可逆(規則さえあれば誰でも戻せる) |
| 鍵の有無 | なし | あり(秘密鍵・公開鍵) | なし |
| セキュリティ | 高(一方向性) | 高(鍵の秘匿性に依存) | なし(秘匿性ゼロ) |
| 出力サイズ | 固定長 | 入力に依存 | 入力より大きくなることが多い |
| 代表例 | MD5, SHA-256, bcrypt | AES, RSA, ChaCha20 | Base64, URLエンコード |
| 主な用途 | パスワード保存・整合性検証 | 通信の暗号化・データ保護 | バイナリデータのテキスト化 |
Base64との違い
Base64は変換規則が公開されており、誰でも元のデータに戻すことができます(デコード)。「エンコード」であってセキュリティ機能はありません。たとえば aGVsbG8= が hello のBase64であることは誰でも確認できます。Base64の詳しい解説はBase64エンコードとは?をご覧ください。
コード例
JavaScript(Web Crypto API)
// ブラウザ・Node.js 18+ で動作
async function sha256(text) {
const encoder = new TextEncoder();
const data = encoder.encode(text);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
// 使用例
const hash = await sha256('hello');
console.log(hash);
// => 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Python(標準ライブラリ)
import hashlib
# SHA-256
text = "hello"
hash_sha256 = hashlib.sha256(text.encode('utf-8')).hexdigest()
print(hash_sha256)
# => 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
# MD5(チェックサム用途のみ)
hash_md5 = hashlib.md5(text.encode('utf-8')).hexdigest()
print(hash_md5)
# => 5d41402abc4b2a76b9719d911017c592
# パスワード保存にはbcryptを使う(pip install bcrypt)
import bcrypt
password = b"my_secret_password"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
print(bcrypt.checkpw(password, hashed)) # True
コマンドライン(Linux/macOS)
# SHA-256ハッシュを計算
echo -n "hello" | sha256sum
# => 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
# ファイルのSHA-256を確認
sha256sum downloaded-file.iso
# macOSの場合
echo -n "hello" | shasum -a 256