
暗号学において、HMAC (鍵付きハッシュメッセージ認証コードまたはハッシュベースメッセージ認証コードとも呼ばれる)は、暗号ハッシュ関数と秘密暗号鍵を用いたメッセージ認証コード(MAC)の一種です。他のMACと同様に、メッセージのデータ整合性と真正性を同時に検証するために使用できます。HMACは鍵付きハッシュ関数の一種であり、鍵導出方式や鍵ストレッチ方式でも使用できます。
HMACは、非対称暗号を用いたデジタル署名の代わりに、共有秘密鍵を用いた認証を提供します。通信当事者に鍵交換を委任することで複雑な公開鍵基盤の必要性をなくし、通信前に信頼できるチャネルを確立して鍵について合意する責任を担います。
HMACの計算には、SHA-2やSHA-3などの任意の暗号ハッシュ関数を使用できます。結果として得られるMACアルゴリズムはHMAC- xと呼ばれます。ここで、xは使用されるハッシュ関数(例:HMAC-SHA256またはHMAC-SHA3-512)です。HMACの暗号強度は、基礎となるハッシュ関数の暗号強度、ハッシュ出力のサイズ、および鍵のサイズと品質に依存します。[ 1 ]
HMACはハッシュ計算を2パス行います。どちらのパスでも、秘密鍵を用いて内部鍵と外部鍵の2つの鍵を導出します。次に、ハッシュアルゴリズムの最初のパスでは、メッセージと内部鍵から内部ハッシュが生成されます。2番目のパスでは、内部ハッシュの結果と外部鍵から最終的なHMACコードが生成されます。このように、このアルゴリズムは長さ拡張攻撃に対する耐性を高めています。
反復ハッシュ関数(Merkle-Damgård構造を用いるもの)は、メッセージを固定サイズのブロックに分割し、圧縮関数を用いてそれらを反復処理します。例えば、SHA-256は512ビットのブロックで動作します。HMACの出力サイズは、基礎となるハッシュ関数のサイズと同じです(例えば、SHA-256の場合は256ビット、SHA3-512の場合は512ビット)。ただし、必要に応じて切り捨てることもできます。
HMACはメッセージを暗号化しません。その代わりに、メッセージ(暗号化の有無にかかわらず)はHMACハッシュと共に送信する必要があります。秘密鍵を持つ当事者はメッセージを再度ハッシュ化し、メッセージが本物であれば、受信したハッシュと計算されたハッシュが一致します。
HMAC構造の定義と分析は、1996年にMihir Bellare、Ran Canetti、Hugo Krawczykによる論文で初めて発表されました。[ 1 ] [ 2 ]彼らは1997年にRFC 2104も執筆しました。[ 3 ]:§2 1996年の論文では、NMAC(Nested MAC)と呼ばれるネストされた変種も定義されています。FIPS PUB 198は、HMACの使用を一般化し、標準化しています。[ 4 ] HMACは、 IPsec、[ 2 ] SSHおよびTLSプロトコル、およびJSON Web Tokensで使用されます。
この定義は RFC 2104 から引用したものです。
どこ
ハッシュ関数H | b、バイト | L、バイト |
|---|---|---|
| MD5 | 64 | 16 |
| SHA-1 | 64 | 20 |
| SHA-224 | 64 | 28 |
| SHA-256 | 64 | 32 |
| SHA-512/224 | 128 | 28 |
| SHA-512/256 | 128 | 32 |
| SHA-384 | 128 | 48 |
| SHA-512 | 128 | 64 [ 5 ] |
| SHA3-224 | 144 | 28 |
| SHA3-256 | 136 | 32 |
| SHA3-384 | 104 | 48 |
| SHA3-512 | 72 | 64 [ 6 ] |
out = H(in)L = length(out)b = H's internal block length[ 3 ] : §2 | ||
以下の擬似コードはHMACの実装方法を示しています。SHA-1、MD5、RIPEMD-128のいずれかのハッシュ関数を使用する場合、ブロックサイズは512ビット(64バイト)です。[ 3 ]:§2
関数hmacの入力: key: Bytes // バイト配列 message: Bytes // ハッシュするバイト配列 hash: Function // 使用するハッシュ関数 (例: SHA-1) blockSize: Integer // ハッシュ関数のブロックサイズ (例: SHA-1 の場合は 64 バイト)// ブロックサイズのキーを計算する block_sized_key = computeBlockSizedKey(キー, ハッシュ, ブロックサイズ) o_key_pad ← block_sized_key xor [0x5c blockSize] // 外側のパディングされたキー i_key_pad ← block_sized_key xor [0x36 blockSize] // 内側のパディングされたキー ハッシュ(o_key_pad ‖ ハッシュ(i_key_pad ‖ メッセージ))を返します関数computeBlockSizedKey の入力は次のとおりです: key: Bytes // バイト配列 hash: Function // 使用するハッシュ関数 (例: SHA-1) blockSize: Integer // ハッシュ関数のブロックサイズ (例: SHA-1 の場合は 64 バイト)// blockSizeよりも長いキーはハッシュ化によって短縮されますif (length(key) > blockSize) then キー = ハッシュ(キー) // blockSizeより短いキーは、右側にゼロを埋め込んでblockSizeに合わせます。if ( length(key) < blockSize) then return Pad(key, blockSize) // キーをゼロで埋めて、blockSizeバイトの長さにします。リターン キー
HMAC仕様の設計は、鍵とハッシュ関数を組み合わせるより単純なメカニズムに対する攻撃の存在を念頭に置いて行われました。例えば、HMACが提供するのと同じセキュリティは、MAC = H (鍵‖メッセージ) で実現できると考えるかもしれません。しかし、この方法には重大な欠陥があります。ほとんどのハッシュ関数では、鍵を知らなくてもメッセージにデータを追加して、別の有効なMACを取得することが容易です(「長さ拡張攻撃」)。代替案であるMAC = H (メッセージ‖鍵)を使用して鍵を追加する方法は、(鍵なしの)ハッシュ関数の衝突を発見した攻撃者が、MACにも衝突を起こすという問題を抱えています(同じハッシュを生成する2つのメッセージ m1 と m2 は、追加された鍵がハッシュされる前にハッシュ関数に同じ開始条件を提供するため、最終的なハッシュは同じになります)。MAC = H (鍵‖メッセージ‖鍵) を使用する方が優れていますが、2つの異なる鍵を使用する場合であっても、この方法には脆弱性があることが様々なセキュリティ論文で指摘されています。[ 1 ] [ 7 ] [ 8 ]
現在のHMAC仕様はH ( key ‖ H ( key ‖ message ))と定義されていますが、ハッシュ関数の外部適用によって内部ハッシュの中間結果がマスクされるため、拡張攻撃は発見されていません。ipadとopadの値はアルゴリズムのセキュリティにとって重要ではありませんが、互いに大きなハミング距離を持つように定義されているため、内部キーと外部キーの共通ビット数が少なくなります。HMACのセキュリティ低下には、これらの値が少なくとも1ビット異なることが必要です。
NISTによってSHA-3コンペティションの優勝者として選ばれたKeccakハッシュ関数は、このネストされたアプローチを必要とせず、長さ拡張攻撃の影響を受けないため、メッセージの先頭にキーを追加するだけでMACを生成することができます。[ 9 ]
HMACの暗号強度は、使用される秘密鍵のサイズと、基礎となるハッシュ関数のセキュリティに依存します。HMAC構造のセキュリティは、使用されるハッシュ関数のセキュリティ特性に直接関係していることが証明されています。HMACに対する最も一般的な攻撃は、秘密鍵を暴くためのブルートフォース攻撃です。HMACは、基礎となるハッシュアルゴリズム単体よりも衝突の影響を大幅に受けにくくなっています。[ 2 ] [ 10 ] [ 11 ] 特に、Mihir Bellareは、圧縮関数が疑似乱数関数(PRF)であるという仮定のもと、HMACが疑似乱数関数(PRF)であることを証明しました。[ 12 ]したがって、HMAC-MD5はMD5で発見されたのと同じ弱点を抱えていません。[ 13 ]
RFC 2104では、「Bバイトより長いキーはまずHを用いてハッシュする」ことが求められており、これは紛らわしい擬似衝突を引き起こします。キーがハッシュブロックサイズ(例えばSHA-1の場合は64バイト)より長い場合、HMAC(k, m)は として計算されますHMAC(H(k), m)。この特性は、パスワードハッシュのシナリオにおいてHMACの潜在的な弱点として挙げられることがあります。長いASCII文字列と、ハッシュもASCII文字列となるランダムな値を見つけることが可能であり、両方の値が同じHMAC出力を生成することが実証されています。[ 14 ] [ 15 ] [ 16 ]
2006年、Jongsung Kim、Alex Biryukov、Bart Preneel、およびSeokhie Hongは、 MD5とSHA-1の縮小版、またはHAVAL、MD4、SHA-0の完全版を使用したHMACを、ランダム関数またはランダム関数を使用したHMACと区別する方法を示した。差分識別子を使用すると、攻撃者はHMACの偽造攻撃を考案できる。さらに、差分識別子と矩形識別子は、第二原像攻撃につながる可能性がある。この知識があれば、MD4の完全版を使用したHMACを偽造できる。これらの攻撃はHMACのセキュリティ証明と矛盾しないが、既存の暗号ハッシュ関数に基づいてHMACへの洞察を提供する。[ 17 ]
2009年、Xiaoyun Wangらは、関連鍵を用いずにHMAC-MD5を区別する攻撃法を提示した。この攻撃法では、MD5を用いたHMACのインスタンス化と、297回のクエリを用いたランダム関数のインスタンス化を、確率0.87で区別することができる[ 18 ] 。
2011年には、 MD5とHMAC-MD5のセキュリティに関する考慮事項をまとめた情報RFC 6151が公開されました。HMAC-MD5については、 MD5ハッシュ関数自体のセキュリティは深刻に侵害されているものの、現在知られている「HMAC-MD5に対する攻撃は、メッセージ認証コードとして使用された場合、実用的な脆弱性を示唆していないように思われる」とまとめられています。ただし、「新しいプロトコル設計では、HMAC-MD5を含む暗号スイートは含めるべきではない」とも付け加えられています。[ 13 ]
2011年5月には、SHAベースのHMACの抽象理論とソースコードを詳述したRFC 6234が公開されました。[ 19 ]
以下に、入力に 8 ビット ASCII、出力に 16 進エンコードを想定した HMAC 値をいくつか示します。
HMAC_MD5("キー", "素早い茶色のキツネは怠け者の犬を飛び越える") = 80070713463e7749b90c2dc24911e275 HMAC_SHA1("キー", "素早い茶色のキツネは怠け者の犬を飛び越える") = de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 HMAC_SHA256("キー", "素早い茶色のキツネは怠け者の犬を飛び越える") = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 HMAC_SHA512("キー", "素早い茶色のキツネは怠け者の犬を飛び越える") = b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a -1やSHA-2とは異なり、Keccakには長さ拡張の脆弱性がないため、HMACのネスト構造は必要ありません。その代わりに、メッセージの先頭に鍵を追加するだけでMACの計算を実行できます。
ただし、衝突が重要でないHMACなどのアプリケーションには影響しません。
ハッシュ関数Hの衝突頻度に基づくもの(「誕生日攻撃」)[PV,BCK2]であり、最低限の妥当性を持つハッシュ関数では全く実用的ではありません。
本論文は、圧縮関数がPRFであるという唯一の仮定の下で、HMACが
PRF
であることを証明している。圧縮関数の擬似乱数性を侵害する既知の攻撃は存在しないため、これは証明に基づく保証を回復するものであり、また、(弱い)衝突耐性が損なわれたハッシュ関数を用いて実装された場合でもHMACが示す攻撃耐性を説明するのにも役立つ。