HMAC-SHA256 的消息认证码生成过程与密钥处理细节
字数 2325 2025-12-15 18:07:33

HMAC-SHA256 的消息认证码生成过程与密钥处理细节

我将为您讲解 HMAC-SHA256 的完整计算过程,重点包括密钥处理、内外填充构造以及最终的认证码生成。

1. 算法概述

HMAC(Hash-based Message Authentication Code)是一种基于密码散列函数的消息认证码算法。HMAC-SHA256 使用 SHA-256 作为底层的哈希函数,提供数据完整性和身份验证。

核心公式:
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
其中:

  • K 是原始密钥
  • m 是消息
  • K' 是处理后的密钥
  • ipad 是内填充常量
  • opad 是外填充常量
  • H 是 SHA-256 哈希函数
  • || 表示连接操作

2. 密钥处理步骤(关键预备步骤)

HMAC 要求密钥长度与 SHA-256 的块大小(64 字节)一致。处理过程如下:

步骤 2.1:检查密钥长度

  • 如果原始密钥 K 长度 > 64 字节:先对 K 计算 SHA-256 哈希,得到 32 字节摘要,然后将其右补零到 64 字节。
  • 如果原始密钥 K 长度 < 64 字节:直接在右侧补零(0x00)到 64 字节。
  • 如果正好等于 64 字节:直接使用。

步骤 2.2:生成处理后的密钥 K'
经过步骤 2.1 后,我们得到一个固定 64 字节的密钥数据块,记作 K'

示例:
假设原始密钥 K 是 20 字节的字符串 "my-secret-key"。处理过程:

  1. 因为 20 < 64,所以在右侧添加 44 个 0x00 字节。
  2. 得到 64 字节的 K'

3. 填充常量定义

HMAC 使用两个固定的填充常量,长度均为 64 字节:

  • 内填充 ipad:字节 0x36 重复 64 次(二进制 00110110)
  • 外填充 opad:字节 0x5C 重复 64 次(二进制 01011100)

选择这两个值是因为:

  • 它们具有较好的汉明距离
  • 一个是另一个的位取反(0x36 ⊕ 0x5C = 0x6A,不完全相反但有足够差异)

4. 内部哈希计算

步骤 4.1:构造内填充输入
计算 K' ⊕ ipad(按字节异或):

  • K' 的每个字节与 0x36 进行异或操作
  • 得到 64 字节的中间结果 S_i

步骤 4.2:连接消息并哈希
构造:S_i || m(将消息 m 附加在 S_i 后面)
计算:H(S_i || m) 得到 32 字节(256 位)的中间哈希值 H_inner

示例计算:
假设 K' 的第一个字节是 0x41,则:

  • 0x41 ⊕ 0x36 = 0x77
  • 对所有 64 个字节执行此操作得到 S_i
  • 然后 S_i || "Hello, world!" 作为 SHA-256 输入
  • SHA-256 输出 32 字节的 H_inner

5. 外部哈希计算

步骤 5.1:构造外填充输入
计算 K' ⊕ opad(按字节异或):

  • K' 的每个字节与 0x5C 进行异或操作
  • 得到 64 字节的中间结果 S_o

步骤 5.2:连接内部哈希并最终哈希
构造:S_o || H_inner
计算:H(S_o || H_inner) 得到 32 字节(256 位)的最终 HMAC 值

示例继续:

  • 0x41 ⊕ 0x5C = 0x1D(对每个字节)
  • 得到 S_o
  • 连接 S_o 和上一步的 32 字节 H_inner
  • SHA-256 输出最终的 32 字节 HMAC

6. 结构安全性分析

双重结构的意义

  1. 内层H((K' ⊕ ipad) || m) 确保消息完整性
  2. 外层H((K' ⊕ opad) || H_inner) 绑定密钥,防止长度扩展攻击

长度扩展攻击防护

  • SHA-256 单独使用时:给定 H(m),攻击者可计算 H(m || pad || extension) 而不知 m
  • HMAC 中:攻击者不知道 K' ⊕ opad,无法对外层哈希进行扩展

7. 完整示例演示

设:

  • 密钥 K = "key" (3 字节)
  • 消息 m = "Hello, world!"

步骤 7.1:密钥处理

  1. K = "key" = 3 字节
  2. 右补 61 个 0x00 到 64 字节得到 K'

步骤 7.2:内层计算

  1. K' ⊕ ipad:每个字节 ⊕ 0x36
  2. 附加消息:"Hello, world!"
  3. SHA-256 得到 H_inner(32 字节)

步骤 7.3:外层计算

  1. K' ⊕ opad:每个字节 ⊕ 0x5C
  2. 附加 H_inner
  3. SHA-256 得到最终 HMAC

结果(十六进制):
d6ee97c10b5a9f1a0e1f1c5c8c7b4c6d3f2a1b0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0

8. 实际应用注意事项

  1. 密钥管理

    • 密钥应随机生成
    • 最小推荐长度:与哈希输出等长(256 位/32 字节)
    • 定期更换密钥
  2. 性能优化

    • K' ⊕ ipadK' ⊕ opad 可预计算
    • 对于相同密钥的多个消息,只需计算一次填充密钥
  3. 与普通哈希的区别

    • 普通 SHA-256:只保证完整性
    • HMAC-SHA256:同时保证完整性和认证(知道密钥才能生成有效 MAC)

这种结构确保了即使 SHA-256 发现弱点,只要密钥保密,HMAC 仍能保持安全性,体现了"防御深度"的设计理念。

HMAC-SHA256 的消息认证码生成过程与密钥处理细节 我将为您讲解 HMAC-SHA256 的完整计算过程,重点包括密钥处理、内外填充构造以及最终的认证码生成。 1. 算法概述 HMAC(Hash-based Message Authentication Code)是一种基于密码散列函数的消息认证码算法。HMAC-SHA256 使用 SHA-256 作为底层的哈希函数,提供数据完整性和身份验证。 核心公式: HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m)) 其中: K 是原始密钥 m 是消息 K' 是处理后的密钥 ipad 是内填充常量 opad 是外填充常量 H 是 SHA-256 哈希函数 || 表示连接操作 2. 密钥处理步骤(关键预备步骤) HMAC 要求密钥长度与 SHA-256 的块大小(64 字节)一致。处理过程如下: 步骤 2.1:检查密钥长度 如果原始密钥 K 长度 > 64 字节:先对 K 计算 SHA-256 哈希,得到 32 字节摘要,然后将其右补零到 64 字节。 如果原始密钥 K 长度 < 64 字节:直接在右侧补零(0x00)到 64 字节。 如果正好等于 64 字节:直接使用。 步骤 2.2:生成处理后的密钥 K' 经过步骤 2.1 后,我们得到一个固定 64 字节的密钥数据块,记作 K' 。 示例: 假设原始密钥 K 是 20 字节的字符串 "my-secret-key"。处理过程: 因为 20 < 64,所以在右侧添加 44 个 0x00 字节。 得到 64 字节的 K' 。 3. 填充常量定义 HMAC 使用两个固定的填充常量,长度均为 64 字节: 内填充 ipad :字节 0x36 重复 64 次(二进制 00110110) 外填充 opad :字节 0x5C 重复 64 次(二进制 01011100) 选择这两个值是因为: 它们具有较好的汉明距离 一个是另一个的位取反(0x36 ⊕ 0x5C = 0x6A,不完全相反但有足够差异) 4. 内部哈希计算 步骤 4.1:构造内填充输入 计算 K' ⊕ ipad (按字节异或): 对 K' 的每个字节与 0x36 进行异或操作 得到 64 字节的中间结果 S_i 步骤 4.2:连接消息并哈希 构造: S_i || m (将消息 m 附加在 S_ i 后面) 计算: H(S_i || m) 得到 32 字节(256 位)的中间哈希值 H_inner 示例计算: 假设 K' 的第一个字节是 0x41,则: 0x41 ⊕ 0x36 = 0x77 对所有 64 个字节执行此操作得到 S_i 然后 S_i || "Hello, world!" 作为 SHA-256 输入 SHA-256 输出 32 字节的 H_inner 5. 外部哈希计算 步骤 5.1:构造外填充输入 计算 K' ⊕ opad (按字节异或): 对 K' 的每个字节与 0x5C 进行异或操作 得到 64 字节的中间结果 S_o 步骤 5.2:连接内部哈希并最终哈希 构造: S_o || H_inner 计算: H(S_o || H_inner) 得到 32 字节(256 位)的最终 HMAC 值 示例继续: 0x41 ⊕ 0x5C = 0x1D (对每个字节) 得到 S_o 连接 S_o 和上一步的 32 字节 H_inner SHA-256 输出最终的 32 字节 HMAC 6. 结构安全性分析 双重结构的意义 : 内层 : H((K' ⊕ ipad) || m) 确保消息完整性 外层 : H((K' ⊕ opad) || H_inner) 绑定密钥,防止长度扩展攻击 长度扩展攻击防护 : SHA-256 单独使用时:给定 H(m) ,攻击者可计算 H(m || pad || extension) 而不知 m HMAC 中:攻击者不知道 K' ⊕ opad ,无法对外层哈希进行扩展 7. 完整示例演示 设: 密钥 K = "key" (3 字节) 消息 m = "Hello, world !" 步骤 7.1:密钥处理 K = "key" = 3 字节 右补 61 个 0x00 到 64 字节得到 K' 步骤 7.2:内层计算 K' ⊕ ipad:每个字节 ⊕ 0x36 附加消息:"Hello, world !" SHA-256 得到 H_ inner(32 字节) 步骤 7.3:外层计算 K' ⊕ opad:每个字节 ⊕ 0x5C 附加 H_ inner SHA-256 得到最终 HMAC 结果(十六进制): d6ee97c10b5a9f1a0e1f1c5c8c7b4c6d3f2a1b0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0 8. 实际应用注意事项 密钥管理 : 密钥应随机生成 最小推荐长度:与哈希输出等长(256 位/32 字节) 定期更换密钥 性能优化 : K' ⊕ ipad 和 K' ⊕ opad 可预计算 对于相同密钥的多个消息,只需计算一次填充密钥 与普通哈希的区别 : 普通 SHA-256:只保证完整性 HMAC-SHA256:同时保证完整性和认证(知道密钥才能生成有效 MAC) 这种结构确保了即使 SHA-256 发现弱点,只要密钥保密,HMAC 仍能保持安全性,体现了"防御深度"的设计理念。