HMAC解説:ハッシュベースメッセージ認証の仕組み

16 Jun 2026 293 words

HMAC解説

HMAC(Hash-Based Message Authentication Code)は、暗号学的ハッシュ関数と秘密鍵を組み合わせて、メッセージの整合性と authenticity の両方を検証するメカニズムです。誰でも計算できるプレーンハッシュとは異なり、HMACは認証コードの生成または検証に秘密鍵の知識を必要とします。

SHA256のようなプレーンハッシュは、メッセージが変更されていないことを示しますが、誰が作成したかは証明しません。攻撃者はメッセージを変更した後にハッシュを再計算できるため、受信者は改ざんを検出できません。HMACは秘密鍵をハッシュ計算に組み込むことでこれを解決します。鍵を持つ者のみが有効なHMACを生成できるため、秘密を共有する当事者間でのメッセージ認証に適しています。

HMACの仕組み

HMACは、秘密鍵を使用してハッシュ関数を2回実行します。アルゴリズムはRFC 2104で定義されており、次のように動作します:

  1. 秘密鍵をハッシュ関数のブロックサイズにパディング
  2. パディングされた鍵を内部パディング定数(ipad = 0x36を繰り返し)とXOR
  3. 内部パディング鍵にメッセージを追加
  4. 結果をハッシュ化
  5. パディングされた鍵を外部パディング定数(opad = 0x5Cを繰り返し)とXOR
  6. ステップ4のハッシュを外部パディング鍵に追加
  7. 結果を再度ハッシュ化
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))

この二重ハッシュ方式は長さ拡張攻撃を防ぎ、基盤となるハッシュ関数に脆弱性があっても、HMAC構造が安全であることを保証します。

HMAC vs プレーンハッシュ

特徴 プレーンハッシュ(SHA256) HMAC-SHA256
鍵が必要 いいえ はい
整合性チェック はい はい
認証 いいえ はい
改ざん検出 完全な再計算 鍵なしでも検出可能
最適な用途 ファイルチェックサム API認証
長さ拡張 脆弱 耐性あり

一般的なユースケース

API認証 — クライアントは共有秘密鍵を使用して各リクエストにHMACで署名します。サーバーはHMACを再計算して比較します。一致すれば、リクエストは本物と見なされます。

JWTトークン署名 — JWTは通常、よりシンプルなHMACまたはRSA署名を使用しますが、HMACはJWTの有効なアルゴリズムです(HS256、HS384、HS512)。

Webhook検証 — Stripe、GitHub、Slackなどのサービスは、WebhookペイロードにHMACで署名するため、サービスからの送信であることを検証できます。

セッショントークン — HMACは、データベースに保存せずに偽造不可能なセッショントークンを生成できます。

コード例

PHP

$secret = 'my-secret-key';
$message = 'message-to-authenticate';

// HMACを生成
$hmac = hash_hmac('sha256', $message, $secret);
echo $hmac;

// HMACを検証
$expected = hash_hmac('sha256', $message, $secret);
if (hash_equals($expected, $providedHmac)) {
    echo 'Authentic';
}

Python

import hmac
import hashlib

secret = b'my-secret-key'
message = b'message-to-authenticate'

# HMACを生成
hmac_value = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(hmac_value)

# HMACを検証(定数時間比較)
expected = hmac.new(secret, message, hashlib.sha256).digest()
received = bytes.fromhex(provided_hmac)
if hmac.compare_digest(expected, received):
    print('Authentic')

JavaScript(Node.js)

const crypto = require('crypto');

const secret = 'my-secret-key';
const message = 'message-to-authenticate';

// HMACを生成
const hmac = crypto.createHmac('sha256', secret)
    .update(message)
    .digest('hex');
console.log(hmac);

// 検証
const expected = crypto.createHmac('sha256', secret)
    .update(message)
    .digest();

HMACアルゴリズム

HMACは任意の暗号学的ハッシュ関数を使用できます。アルゴリズム名は通常、「HMAC」にハッシュ名を組み合わせたものです。

アルゴリズム ハッシュ関数 出力サイズ
HMAC-MD5 MD5 128ビット
HMAC-SHA1 SHA-1 160ビット
HMAC-SHA256 SHA-256 256ビット
HMAC-SHA512 SHA-512 512ビット
HMAC-SHA3-256 SHA3-256 256ビット

デフォルトではHMAC-SHA256を使用してください。HMAC-MD5とHMAC-SHA1は、セキュリティ重視のアプリケーションでは非推奨です。

セキュリティに関する考慮事項

鍵のサイズ — 鍵は少なくともハッシュ出力と同じ長さが必要です。HMAC-SHA256の場合は、少なくとも32バイト(256ビット)の鍵を使用してください。より長い鍵はブロックサイズまでハッシュ化されます。

鍵の秘密保持 — HMACのセキュリティは、鍵が秘密であることに完全に依存します。鍵管理システムまたは環境変数を使用してください。ソースコードに鍵をハードコードしないでください。

定数時間比較 — HMAC値の比較には、PHPの hash_equals() やPythonの hmac.compare_digest() のような定数時間比較関数を常に使用してください。タイミング攻撃により、正しいHMACが1バイトずつ漏洩する可能性があります。

リプレイ攻撃 — HMACだけではリプレイ攻撃を防げません。署名付きメッセージにタイムスタンプまたはナンスを含め、サーバー側で検証してください。

オンラインツール

Help2CodeのHMACジェネレーターは、選択したアルゴリズムと秘密鍵を使ってHMAC値を計算します。HMAC実装のテストや、開発中のテストベクトル生成に使用してください。

結論

HMACは、共有秘密鍵と暗号学的ハッシュ関数を使用してメッセージ認証を提供します。APIセキュリティ、Webhook検証、メッセージの整合性と authenticity の両方を検証する必要があるあらゆるシナリオに不可欠です。強力な秘密鍵でHMAC-SHA256を使用し、HMAC値の比較には常に定数時間関数を使用してください。


About this article

HMAC(ハッシュベースメッセージ認証コード)の仕組み、通常のハッシュとの違い、API認証での使用方法を学びます。


Related Articles


Related Tools

Help2Code Logo
Menu