\( \def\vector#1{\boldsymbol{#1}} \)

メッセージ認証コード

Takami Torao Java 11 #MAC #HMAC
  • このエントリーをはてなブックマークに追加

概要

メッセージ認証コード (MAC; message authentication code) はメッセージの完全性を認証付きで保証する暗号学的手法である。鍵の所有者 \(A\) によりメッセージが発行されてから破損や改ざんを受けていないことを同じ鍵の所有者 \(B\) が検証することができる (\(A\) と \(B\) は同一でも良い)。

送信者はメッセージと共通鍵を使用して作成した MAC 値をメッセージと共に送信し、受信者は、同じく自身が持つ共通鍵を使ってメッセージから MAC 値を算出し、受信した MAC 値と一致していればメッセージの完全性が保証される。この方法によって共通鍵を持たない中間者によるメッセージ改ざんを防ぐ事ができる。ただし、実際には中間者が同一のメッセージを繰り返し送信するリプレイ攻撃を防ぐためにメッセージ内にシーケンス番号や日時のような nonce を含める必要がある。

例えば、サーバがセッション情報をクライアントサイドに保存するために MAC による認証コード付きの Cookie を発行することができる。この Cookie はサーバの所有する鍵によって検証を行うためクライアントが改ざんすることはできない。

メッセージの送信者と受信者が共通鍵を共有することによって行われる点がハッシュとは異なる。

MAC 値の生成は MAC 値とメッセージから共有鍵の推測が困難なアルゴリズムであれば使用できる。不可逆ハッシュ関数を用いる方法は HMAC (hash-based message authentication code) と呼ばれる。ブロック暗号を用いる方法は

ハッシュ関数 MAC 電子署名
データ破損の検出
中継者によるデータの意図的な改ざんの検出
共通鍵 公開鍵

Table of Contents

  1. 概要
  2. HMAC
  3. CBC-MAC
  4. KMAC

HMAC

HMAC (hash-based message authentication code) は MAC 値の生成に SHA などの不可逆ハッシュ関数を使用する方法である。

ユーザのパスワードをサーバサイドで保管/照合するケースでは一般的に SALT と不可逆ハッシュ関数を使ってハッシュ化した値を使用する手法がとられている。以下の例は共通鍵に SALT を使いパスワードをメッセージとして HMAC でハッシュ化する例である。

import java.nio.charset.StandardCharsets

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

val UTF8 = StandardCharsets.UTF_8

val algorithm = "HmacSHA224"
val password = "8ErY(cw92TLB".getBytes(UTF8)  // 入力されたパスワード
val salt = "K*t%A-qL6!vg".getBytes(UTF8)      // ランダムなバイト配列
val key = new SecretKeySpec(salt, algorithm)
val mac = Mac.getInstance(algorithm)
mac.init(key)
val encoded = mac.doFinal(password)
println(encoded.map(x => f"$x%02X").mkString) // => 467A4B8E5BD5F3B97D1296401547B5B329A162FC36A679EB53DB9E11

// encoded (28バイト) と、salt または key.getEncoded (12バイト) を保存する

上記の例では共通鍵のエンコード (salt.getEncoded; 12バイト) とパスワードの MAC 値 (encoded; 28バイト = 224ビット) を保存すれば良い。検証時は入力されたパスワードを同じアルゴリズムと共通鍵で MAC 値を算出して同じ値が得られれば同一のパスワードと見なすことができる。

この MAC 値は単に \(H({\rm password} + {\rm salt})\) で得たハッシュ値より強い暗号性能を持つ。例えばハッシュ関数 \(H\) に強衝突性が発見されたとしても HMAC で使っているのであれば直ちに脆弱であるということにはならない。また伸長攻撃への耐性もある。このため、パスワードに基づいて AES などの他の暗号アルゴリズムを使用するケースでは、\(H({\rm password} + {\rm salt})\) によるハッシュ値を cipher として使用するよりも安全である。

CBC-MAC

CBC MAC (cipher block chaining message authentication code) はブロック暗号を使用して MAC を算出するためのアルゴリズムである。メッセージ \(M\) はブロック暗号に適した長さの \(\{m_0, m_1, \cdots, m_n\}\) に分割される。初期状態のベクトル \(\vector{0}\) から開始し、直前の結果と \(m_i\) との XOR からブロック暗号を算出することを繰り返し、最終的な結果を MAC 値として使用する。

CBC MAC アルゴリズムは任意長メッセージに対して脆弱であることから、そのようなメッセージに対しては CMAC を使う必要がある。

CBC-MAC
CBC-MAC の算出手順

KMAC

KMAC は SHA-3 の派生アルゴリズムであり、可変長出力関数の cSHAKE を使用して MAC 値を生成することができる (SHA-3 は伸張攻撃を持たないため HMAC に SHA-3 を組み合わせることはあまり意味がない)。