HMAC 生成

SHA-1・SHA-256・SHA-384・SHA-512 で任意のメッセージと秘密鍵から HMAC 署名を計算。hex・base64・base64url 出力に対応。

メッセージ認証コードをローカルで。 HMAC はハッシュ関数と秘密鍵を組み合わせ、受信者が完全性と真正性を両方検証できるようにします。Web Crypto API でブラウザ内計算。

HMAC は何のためにあるのか

暗号化ではなく認証

HMAC は何も隠しません。答えるのは別の問いです。このメッセージはまさに共有秘密を持つ者が生成したものか、そしてそれ以降改変されていないか。出力は固定長のタグで、メッセージと一緒に送ります。受信側は同じ鍵で再計算して比較します。タグが一致すればメッセージは正当かつ無傷、一致しなければどちらでもなく、どちらが原因かを区別する方法はありません。

このためHMAC は webhook 署名、API リクエスト署名、署名付き Cookie、セッショントークンを支える主力になっています。Stripe や GitHub をはじめ多くの webhook 提供者はこの方式でペイロードに署名しており、リクエストが本当に彼らから来たものか、エンドポイント URL を推測した誰かから来たものかを検証できます。

鍵とメッセージを単純に連結してハッシュしない理由

一見自然な構成である SHA256(鍵 + メッセージ) は、SHA-1 や SHA-256 のような Merkle-Damgård 型ハッシュに対して破られます。これらのハッシュはデータをブロック単位で処理し内部状態を引き継ぐため、有効なダイジェストを知る攻撃者は鍵を知らないままデータを追記し、拡張後のメッセージに対する有効なダイジェストを計算できます。これが長さ拡張攻撃であり、理論上の話ではなく実在の API を破ってきました。

HMAC の入れ子構成 H(鍵 XOR opad || H(鍵 XOR ipad || メッセージ)) はこの穴をふさぎます。異なるパディング鍵で 2 回処理することで、最終ダイジェストは攻撃者が影響できるデータに対するハッシュの生の内部状態ではなくなります。独自の鍵付きハッシュを考案せず、常に HMAC を使うべき理由がこれです。

実務上の注意

外部要因で縛られていないかぎり SHA-256 を選んでください。SHA-1 は HMAC の内部では今も安全です。この構成は衝突耐性に依存しないためですが、新規システムで使う理由はなく、監査でも指摘されます。SHA-512 はこの用途で実質的に強いわけではなく、64 ビットハードウェアでは速いことがある程度です。

ハッシュの選択より重要な実装上の要点が 2 つあります。1 つ目はタグの比較を定数時間で行うこと。通常の文字列比較は最初に異なるバイトで打ち切るため、そのタイミング情報だけで 1 バイトずつタグを偽造できてしまいます。2 つ目は鍵をダイジェスト長以上のランダムバイトにすること。覚えやすいパスフレーズは不可です。HMAC の鍵はパスワードハッシュではなく、ストレッチングは一切行われません。

オープンソースに関する注記:ブラウザ標準の Web Crypto(crypto.subtle)API で実装。サードパーティライブラリは使用していません。

よくある質問

秘密鍵はどこかに送信されますか?
いいえ。鍵とメッセージがブラウザの外に出ることはありません。署名は Web Crypto API でローカルに計算され、送信も保存も行われません。
どのアルゴリズムを選ぶべきですか?
新規開発では SHA-256 を使ってください。SHA-384 と SHA-512 はわずかなコストで安全余裕を高めます。SHA-1 は旧システムとの相互運用のためだけに残されています。
base64 と base64url の違いは何ですか?
base64url は + と / を - と _ に置き換え、パディングを省きます。そのため URL・ファイル名・HTTP ヘッダーにそのまま入れても安全です。
HMAC は暗号化の一種ですか?
いいえ。鍵の保持者が作成したことと改ざんされていないことは証明できますが、メッセージ自体は読めるままです。秘匿性も必要なら TLS や暗号化を併用してください。
鍵とメッセージを連結してハッシュするだけでは駄目ですか?
素の SHA-2 は長さ拡張攻撃に弱く、鍵を知らなくても署名済みメッセージにデータを追加して正当なダイジェストを偽造できます。HMAC の入れ子構造がこれを防ぎます。
コード内で 2 つの HMAC を比較するには?
crypto.timingSafeEqual のような定数時間比較を使ってください。通常の == は最初に異なるバイトで終了するため、正しい署名を 1 バイトずつ推測される恐れがあります。