TL

ハッシュ関数の内部構造(Merkle–Damgård と SHA-3 のスポンジ構造)

SHA-256 と SHA-3 の作りの違いを、Merkle–Damgård とスポンジ構造から分解。長さ拡張攻撃への耐性差まで原理で理解できます。

応用ハッシュSHA-256SHA-3暗号Keccak最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.SHA-256 は Merkle–Damgård 構造。固定長の圧縮関数を、前ブロックの出力を引き継ぎながら反復し、最後の内部状態をそのまま出力する。長さ拡張攻撃の余地はこの「内部状態=出力」に起因する。
  • 2.SHA-3/Keccak はスポンジ構造。広い内部状態の一部(レート部 r)にだけ入力を混ぜて置換 f を回す吸収相と、同じ状態から少しずつ取り出す搾出相に分かれ、容量部 c は外から触れない。
  • 3.容量部が出力に晒されないため SHA-3 は長さ拡張攻撃が原理的に成立しない。SHA-256 はその回避に HMAC や SHA-512/256 を要する。

ハッシュ関数は「任意長→固定長」をどう実現するか

暗号学的ハッシュ関数は任意長の入力を固定長の出力へ写します。だが暗号プリミティブの中核は、たいてい固定長しか扱えません。SHA-256 の中身は 512 ビット入力を取る圧縮関数、SHA-3 は 1600 ビット状態への置換です。この「固定長の部品で任意長を処理する」橋渡しの設計が構造(construction)であり、SHA-2 系の Merkle–Damgård と SHA-3 のスポンジは、ここで思想が真っ向から分かれます。構造を理解すると、衝突耐性や長さ拡張攻撃といった性質が「なぜそうなるか」が見えてきます。前提となる一方向性や衝突耐性の定義は 暗号の基礎 を参照してください。

Merkle–Damgård 構造:圧縮関数の反復

Merkle–Damgård(MD)構造は、二入力を一出力にまとめる圧縮関数 f: {chaining値, メッセージブロック} → chaining値 を反復します。手順はこうです。

1. パディング: メッセージ末尾に 1 ビットの 1、0 を詰め、最後に
   「元のメッセージ長」を符号化して付与する(長さ詰め=MDストレングス化)
2. 固定長ブロック M1, M2, ..., Mn に分割
3. H0 = IV(規格で固定された初期値)
4. for i in 1..n:  Hi = f(Hi-1, Mi)   ← 前段の出力を次段へ引き継ぐ
5. 出力 = Hn(最後の chaining 値そのもの)

要点は2つ。ひとつは末尾に必ずメッセージ長を埋め込むこと(Merkle–Damgård strengthening)。これにより、長さの異なるメッセージが偶然同じパディング後系列にならず、構造由来の衝突を防ぎます。もうひとつは、圧縮関数 f が衝突耐性を持てば、全体も衝突耐性を持つことが証明されている点です(Merkle–Damgård 定理)。設計者は固定長の f の安全性に集中すればよく、これが MD の強みでした。

チェーン値こそが状態

MD構造の内部状態は chaining 値 Hi ただひとつです。SHA-256 なら 256 ビット。各ブロックを食べるたびにこの 256 ビットが更新され、最後の値がそのまま出力になります。「内部状態の全部が出力に出る」――この一点が、後述の長さ拡張攻撃の入口になります。

SHA-256 の処理を分解する

SHA-256 は MD 構造の代表です。圧縮関数は 256 ビットの chaining 値(a から h の8ワード)と 512 ビットメッセージブロックを取り、64 ラウンドの混合を行います。

入力: 8ワードの状態(a..h) と 512ビットブロック
1. メッセージスケジュール: 512ビットを16ワード(W0..W15)に分け、
   W16..W63 を σ0/σ1(ローテートとシフトのXOR)で再帰生成
2. 64ラウンド: 各ラウンドで
     T1 = h + Σ1(e) + Ch(e,f,g) + Kt + Wt
     T2 = Σ0(a) + Maj(a,b,c)
   を計算し、a..h を1つずつローテートしながら更新
   (Ch=選択, Maj=多数決, Σ/σ=ビット回転と排他的論理和の混合)
3. 最後に入力状態 a..h を加算(Davies–Meyer 風の前後加算)

ラウンド関数はビット回転・シフト・加算・XOR・非線形関数 Ch/Majだけで構成され、入力1ビットの変化が出力全体へ伝播する雪崩効果を生みます。最後の「入力状態の加算」は重要で、f を一方向にする(圧縮関数からブロック暗号を作る Davies–Meyer 構成に対応)役割を担います。SHA-224 は SHA-256 と IV と出力長だけが違い、SHA-384/512 は 64 ビットワード・1024 ビットブロック・80 ラウンドへ拡張した同系統で、いずれも骨格は同じ MD+類似ラウンドです。ファイル改ざん検知でこの出力(ダイジェスト)を使う発想は ハッシュ化と暗号化の違い で扱った通りです。

長さ拡張攻撃:MD構造の構造的弱点

MD構造には**長さ拡張攻撃(length extension attack)**という固有の弱点があります。出力が「最後の chaining 値そのもの」だからです。

攻撃者が hash(secret || message) の値と message の長さだけを知っているとします。すると secret を知らなくても、そのハッシュ値を内部状態として復元し、続きから計算を再開できます。結果、hash(secret || message || padding || 攻撃者の追記) の正しいハッシュを偽造できてしまう。

naïve な MAC 構成は壊れる

MAC = SHA-256(secret_key || message) でメッセージ認証コードを作る素朴な実装は、長さ拡張攻撃で偽造されます。攻撃者は得られた MAC を「途中状態」として使い、message の末尾に任意データを足した新メッセージの正規 MAC を、鍵を知らずに生成できます。だから鍵付きハッシュには HMAC を使うのが鉄則です。HMAC は H(key XOR opad || H(key XOR ipad || message)) と二重にハッシュをネストし、外側のハッシュで内部状態を覆い隠すことでこの攻撃を封じます。

回避策は3つあります。(1) HMAC を使う(最も標準的)。(2) 出力を切り詰めた変種を使う――SHA-512/256 は内部 512 ビット状態の半分しか出力しないため、攻撃者は完全な内部状態を得られず長さ拡張が成立しません。(3) そもそも晒さない構造のハッシュ=SHA-3 を選ぶ。SHA-256 の生の出力をそのまま secret || data 形式の認証に使わないこと、これが実務上の要点です。

スポンジ構造:吸収と搾出

SHA-3(Keccak)は MD と無関係なスポンジ構造(sponge construction)を採用します。中心にあるのは圧縮関数ではなく、固定幅の置換 f(Keccak-f[1600]、1600 ビットの可逆変換)です。内部状態 b ビットを レート部 r容量部 c に分け(b = r + c)、入力はレート部にだけ触れます。

状態 S = r ビット || c ビット(初期は全 0、合計 1600 ビット)

吸収相 (absorbing):
  入力をパディングして r ビットのブロック P1..Pn に分割
  for each Pi:
    S[レート部] = S[レート部] XOR Pi   ← 入力はレート部にだけXOR
    S = f(S)                            ← 1600ビット全体を撹拌

搾出相 (squeezing):
  必要な出力長になるまで:
    出力に S のレート部 r ビットを取り出す
    (まだ足りなければ S = f(S) を回して続きを絞る)

スポンジ=海綿の比喩通り、入力を吸い込み(吸収)、撹拌した状態から欲しい分だけ絞り出す(搾出)。搾出相が独立しているため、SHA-3 は同じ構造のまま任意長出力(SHAKE128/256 の XOF)も自然に表現できます。これは固定長出力に縛られる MD には真似のしにくい柔軟性です。

容量部 c は外から触れない

スポンジの肝は容量部 c が入力でも出力でも直接アクセスされないこと。入力XORはレート部だけ、出力取り出しもレート部だけで、c はずっと f の内部で撹拌され続けます。この「触れない秘密の領域」がスポンジの安全性の源泉です。SHA3-256 では c = 512r = 1088。各種パラメータの正規定義はFIPS 202が一次資料です。

Keccak-f 自体は、5×5×64 ビットの3次元配列状態に対し θ(列パリティ拡散)ρ(ビット回転)π(レーン置換)χ(唯一の非線形ステップ)ι(ラウンド定数XOR)の5工程を24ラウンド適用します。AESのような S-box ルックアップを使わず論理演算中心なので、サイドチャネル耐性やハードウェア実装で有利という設計上の利点もあります。

構造の違いが生む攻撃耐性の差

両構造を性質ごとに対比します。

性質Merkle–Damgård(SHA-256)スポンジ(SHA-3)
中核プリミティブ圧縮関数 f(固定長を圧縮)置換 f(固定幅を撹拌・可逆)
内部状態と出力chaining値がそのまま出力に露出容量部 c は出力に出ない
長さ拡張攻撃成立する(HMAC等で回避が必要)原理的に成立しない
可変長出力(XOF)不可(SHAKE相当を持たない)搾出を延ばすだけで自然に対応
衝突耐性の根拠MD定理:f の衝突耐性に帰着容量部 c で決まる(約 c/2 ビット)

最大の差は長さ拡張攻撃です。SHA-3 は出力が容量部に守られた状態の一部にすぎず、攻撃者は完全な内部状態(1600 ビット)を復元できません。レート部 r は見えても、撹拌され続ける c が分からない限り f を正しく再開できないため、攻撃は原理的に不可能になります。一方 SHA-256 は内部状態そのものが出力なので、追加の構成(HMAC)でしか守れません。

「SHA-3 は SHA-256 より強い」ではない

SHA-3 が選ばれたのは「SHA-2 が破られたから」ではありません。SHA-256 は現在も衝突・原像攻撃に対して安全とされています。SHA-3 制定の動機は、MDとは異なる設計を標準として持ち、将来 SHA-2 系に構造的弱点が見つかった場合の保険(暗号アジリティ)を確保することでした。実務では速度や実装の都合で SHA-256 が依然主流です。「新しい=常に優先」ではなく、長さ拡張のような構造的性質が要件に効くかで選ぶのが正解です。

押さえどころ
  • MD構造=圧縮関数の反復、末尾に長さを埋め込む(strengthening)、内部状態がそのまま出力。
  • 長さ拡張攻撃は MD 固有。鍵付き認証には生ハッシュ連結ではなく HMAC を使う。
  • スポンジ=吸収/搾出。レート部 r にだけ入出力が触れ、容量部 c は隠れる。c が衝突・原像の安全余裕(概ね c/2)を決める。
  • SHA-3 は長さ拡張が原理的に不成立、XOF(SHAKE)が自然に作れるのが構造上の利点。

ハッシュ関数を「ブラックボックスの一方向変換」で済ませず、f の反復か置換の吸収・搾出かまで分解できると、HMAC が必要な理由や SHA-512/256 という変種の存在意義が腑に落ちます。実際にパスワード保存で低速ハッシュを選ぶ判断(パスワードの安全な保存)も、こうした内部構造の理解が土台になります。

セキュリティ Article

ハッシュ関数の内部構造(Merkle–Damgård と SHA-3 のスポンジ構造)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

ハッシュ

比較で見る軸

難易度: advanced / カテゴリ: セキュリティ / タグ数: 5

導入後に効く点

SHA-3/Keccak はスポンジ構造。広い内部状態の一部(レート部 r)にだけ入力を混ぜて置換 f を回す吸収相と、同じ状態から少しずつ取り出す搾出相に分かれ、容量部 c は外から触れない。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
セキュリティ
タグ数
5

判断チェックリスト

  • 自社の用途が「ハッシュ / SHA-256」に近いか確認する。
  • 強みである「SHA-256 は Merkle–Damgård 構造。固定長の圧縮関数を、前ブロックの出力を引き継ぎながら反復し、最後の内部状態をそのまま出力する。長さ拡張攻撃の余地はこの「内部状態=出力」に起因する。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

ハッシュSHA-256SHA-3暗号KeccakハッシュSHA-256SHA-3
参考: 公式情報