HMAC - 訊息完整性與身份驗證

在資訊安全的領域中,確保資料在傳輸過程中未被竄改(完整性)以及確認訊息來源的真實性(身份驗證)是至關重要的課題。訊息鑑別碼 (Message Authentication Code, MAC) 正是為此而生的技術,而其中,HMAC (Hash-based Message Authentication Code) 則是最廣泛應用且安全可靠的一種實現方式。

本文將探討 HMAC 的核心概念、運作原理,以及如何在 Python 中實作 HMAC,讓您能夠輕鬆地為您的應用程式增添訊息完整性與身份驗證的保障。

什麼是 MAC?

訊息鑑別碼 (MAC) 是一種透過密鑰(金鑰)與訊息內容所產生的一小段資訊,用於附加在原始訊息之後。接收方可以使用相同的密鑰與接收到的訊息,重新計算一次 MAC 值,並與收到的 MAC 值進行比對。如果兩者相符,接收方就能夠確信:

  1. 資料完整性 (Data Integrity): 訊息在傳輸過程中沒有被任何未經授權的第三方修改。
  2. 身份驗證 (Authentication): 訊息確實來自於持有相同密鑰的發送方。

常見的 MAC 類型包含基於區塊加密演算法的 CBC-MAC、CMAC,以及本文的主角——基於雜湊函式的 HMAC。image size

HMAC 的核心概念

HMAC,全名為「雜湊訊息鑑別碼」,其核心宗旨在於利用密碼學中的雜湊函式(如 SHA-256、SHA-512 等)來產生 MAC。它的設計巧妙地將一個密鑰整合到雜湊運算的過程中,彌補了單純使用雜湊函式(例如 hash(key || message))可能存在的安全漏洞。

HMAC 的標準由 RFC 2104 等文件所定義,其設計目標是即使底層的雜湊函式存在某些弱點,HMAC 結構本身也能提供高度的安全性。

HMAC 的運作原理

HMAC 的計算過程可以透過以下偽代碼來理解,這也是其標準定義的核心步驟:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function hmac (key, message)  
// 步驟 1: 處理金鑰
if (length(key) > blocksize) then
// 若金鑰長度大於雜湊函式的區塊大小,則先對金鑰進行雜湊
key = hash(key)
else if (length(key) < blocksize) then
// 若金鑰長度小於區塊大小,則在後面補 0 直到與區塊大小相等
key = key || zero-padded
end if

// 步驟 2: 產生內部與外部填充金鑰
o_key_pad = [0x5c * blocksize] XOR key // 外部金鑰 (Outer Key)
i_key_pad = [0x36 * blocksize] XOR key // 內部金鑰 (Inner Key)

// 步驟 3: 執行雙重雜湊運算
// 第一次雜湊:將內部金鑰與訊息串接後進行雜湊
inner_hash = hash(i_key_pad || message)
// 第二次雜湊:將外部金鑰與第一次的雜湊結果串接後,再進行一次雜湊
return hash(o_key_pad || inner_hash)
end function

運作流程解析:

  1. 金鑰預處理: 為了確保金鑰長度的一致性與安全性,演算法會先對金鑰進行標準化處理。
  2. 派生內外金鑰: 演算法使用兩個固定的常數 0x36 (ipad, inner pad) 和 0x5c (opad, outer pad) 與處理過的金鑰進行 XOR 運算,產生兩個不同的派生金鑰。這個步驟是 HMAC 安全性的關鍵,它讓攻擊者即使在知道 hash(i_key_pad || message) 的情況下,也無法輕易推算出原始金鑰或偽造最終的 HMAC 值。
  3. 雙重雜湊: HMAC 執行了兩次雜湊運算。第一次是將訊息與內部金鑰結合,第二次則是將第一次的雜湊結果與外部金鑰結合。這種「包裹式」的雜湊結構,確保了訊息和金鑰被緊密地混合在一起,提供了極高的抗攻擊能力。

Python 實作範例

理論之外,我們可以透過 Python 內建的 hmac 函式庫,輕鬆地實作 HMAC 的生成與驗證。以下程式碼示範了如何使用 HMAC-SHA256。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import hmac  
import hashlib

def generate_hmac(key, msg):
"""
使用指定的金鑰和訊息生成 HMAC-SHA256 簽章。

Args:
key (bytes): 用於簽章的密鑰。
msg (bytes): 要簽章的訊息。

Returns:
str: 十六進位格式的 HMAC 簽章。
"""
# 建立一個 hmac 物件,使用 SHA256 作為雜湊演算法
h = hmac.new(key, msg, hashlib.sha256)

# 返回十六進位的摘要 (digest)
return h.hexdigest()

def verify_hmac(key, msg, signature):
"""
驗證 HMAC 簽章是否有效。

Args:
key (bytes): 用於簽章的密鑰。
msg (bytes): 要簽章的訊息。
signature (str): 要驗證的 HMAC 簽章 (十六進位格式)。

Returns:
bool: 如果簽章有效則返回 True,否則返回 False。
"""
# 重新計算一次簽章
expected_signature = generate_hmac(key, msg)

# 使用 hmac.compare_digest 來安全地比較兩個簽章
# 這樣可以防止時序攻擊 (timing attacks)
return hmac.compare_digest(expected_signature, signature)

# --- 主程式 ---
if __name__ == "__main__":
# 1. 定義密鑰和訊息
# 重要:在真實應用中,密鑰絕不應該寫死在程式碼中!
# 密鑰和訊息都必須是位元組 (bytes) 型態,所以我們在字串前加上 'b'
secret_key = b'my-secret-key-is-very-secret'
message = b'This is the message to be signed.'

print(f"原始訊息: {message.decode()}")
print(f"使用的密鑰: {secret_key.decode()}")
print("-" * 30)

# 2. 發送方:生成 HMAC 簽章
signature = generate_hmac(secret_key, message)
print(f"產生的 HMAC-SHA256 簽章: {signature}")
print("-" * 30)

# --- 模擬傳輸 ---
# 在網路中,發送方會將 `message` 和 `signature` 一起傳送給接收方。

# 3. 接收方:驗證簽章
print("接收方開始驗證簽章...")

# 情況 A: 成功的驗證 (訊息和密鑰都正確)
is_valid = verify_hmac(secret_key, message, signature)
print(f"情況 A (資料未被竄改): 驗證結果 -> {'有效' if is_valid else '無效'}")

# 情況 B: 失敗的驗證 (訊息被竄改)
tampered_message = b'This is the message to be SIGNED.' # 訊息被稍微修改
is_valid_tampered = verify_hmac(secret_key, tampered_message, signature)
print(f"情況 B (資料已被竄改): 驗證結果 -> {'有效' if is_valid_tampered else '無效'}")

這個範例清楚地展示了 HMAC 的生命週期:發送方生成簽章,而接收方進行驗證。只有當訊息與密鑰完全吻合時,驗證才會通過。

HMAC 的應用與標準

HMAC 的彈性在於它可以與多種不同的雜湊函式搭配使用,形成不同的演算法,例如:

  • HMAC-SHA256: 使用 SHA-256 作為底層雜湊函式。
  • HMAC-SHA384: 使用 SHA-384 作為底層雜湊函式。
  • HMAC-SHA512: 使用 SHA-512 作為底層雜湊函式。

在實際應用中,HMAC 被廣泛整合於各種安全協定與標準中,例如在 PKCS#11(密碼學權杖介面標準)中,就定義了 CKM_SHA256_HMAC 等多種機制,讓硬體安全模組 (HSM) 能夠安全地執行 HMAC 運算。

結論

總結來說,HMAC 是一種安全、高效且標準化的訊息鑑別碼演算法。它透過巧妙的雙重雜湊結構,將密鑰與雜湊函式結合,不僅能夠驗證訊息在傳輸過程中是否被竄改,更能確認訊息發送方的身份。正因為其優異的安全性與設計,HMAC 已成為當今網路通訊、API 驗證、資料儲存等眾多場景中,不可或缺的基礎安全工具。

參考資料

  • RFC 2104 - HMAC: Keyed-Hashing for Message Authentication
  • Python hmac module documentation
  • Wikipedia - HMAC

也許你也會想看看