Table of Contents
HMAC (RFC 2104) を Python で実装しました。 ハッシュ関数には ライブラリ にある SHA-256 を使いました。
HMAC の概要
HMAC は、メッセージの送信者の認証とメッセージの改ざんの検出に用いられるメッセージ認証符号(MAC: Message Authentication Code)を生成するための暗号化技術です。 HMACは、ハッシュ関数と秘密鍵を組み合わせて、MACを求めます。
HMACは、以下のような特徴を持ちます。
- 秘密鍵とメッセージの両方に依存してMACを生成するので、秘密鍵を知らない者は同じMACを計算できません。これにより、送信者の認証が可能になります。
- ハッシュ関数を2回適用することで、メッセージの一部を変更してもMACが一致する確率を非常に低くします。これにより、メッセージの改ざんを検知する能力を高めます。
- HMACは、任意のハッシュ関数を用いることができます。例えば、SHA-256やMD5などのハッシュ関数をHMACに適用することができます。
- HMACは、不可逆な暗号化技術です。
手続の説明
RFC 2104 に丁寧に手続きが記載されています。
HMAC に必要なのは、 ハッシュ関数 H と 秘密鍵 K です。
ハッシュ関数 H のブロック長を B バイト, 出力長を L バイト と表すことにします。 ハッシュ関数 H = SHA-256 のときは、 B = 64, L = 32 です。
K は秘密鍵とありますが、 公開鍵暗号における秘密鍵である必要はなく、 他の人に知られることがない秘密の文字列であればOKです。 RFC 2104 では private key ではなく secret key と書かれています。 K の長さは、 RFC では、最低でもハッシュ関数の出力長と記載されています。 K はハッシュ値とのビット演算を行うものであるため、 ハッシュ値より短いと規定の値で埋める必要があり、推測しやすくなるからですね。
HMAC の計算の流れは次のとおりです。
- 秘密鍵 K が ハッシュ関数のブロック長 B よりも長い場合は、 ハッシュ関数によって K を L バイト のハッシュ値に変換します。 生成されたハッシュ値を HMAC で使用する秘密鍵 K とします。
- 秘密鍵 K が ハッシュ関数のブロック長 B よりも短い場合は、 全体で B バイト になるように、 K の末尾に ゼロ (
0x00
) を追加します。 - 上の計算結果と 0x36 を B 回 繰り返した値 (
ipad = b'\x36' * B
) の、 XOR を計算します。 ビット単位の演算です。 - 上の計算結果の後ろに 暗号化したいメッセージ (ビット配列) を加えます。
- 上の計算結果を ハッシュ関数 H によってハッシュ値に変換します。
- 秘密鍵と、 0x5c を B 回 繰り返した値 (
opad = b'\x5c' * B
) の XOR を計算します。 ビット単位の演算です。 - 計算されたハッシュ値を上の計算で得られたXORの後ろに追加します。
- 上の計算結果を ハッシュ関数 H を使ってハッシュ値に変換します。
プログラム
そしてこちらがPythonで記述した HMAC (SHA-256) です。
環境
- Python 3.10.13
コード
HMAC に代わる他のMAC生成方法
HMAC は ハッシュ関数 と 秘密鍵 を組み合わせて MAC を求める方法でした。 MAC を生成する他の方法に、 Keccakハッシュ関数を使用する KMAC, 任意のブロック暗号を使用する CMAC があります。