文章总结: 本文解读国标GB/T15852.2—2024下的HMAC-SM3算法,阐述其密钥扩展、杂凑计算与截断流程。文章分析了算法的安全强度与实现效率,列举网络通信与金融等应用场景,并提供Python脚本演示计算细节,为技术人员掌握该国产密码算法提供了从理论到实现的完整参考。 综合评分: 90 文章分类: 技术标准,数据安全,应用安全,安全开发
【密码算法】HMAC-SM3 消息鉴别码
原创
利刃信安 利刃信安
利刃信安
2026年3月7日 00:04 北京
HMAC-SM3 消息鉴别码
1. 概述
1.1 标准信息
- • 标准名称:GB/T 15852.2—2024《网络安全技术 消息鉴别码 第2部分:采用专门设计的杂凑函数的机制》
- • 发布日期:2024-09-29
- • 实施日期:2025-04-01
- • 代替标准:GB/T 15852.2—2012
1.2 算法基本概念
消息鉴别码能够保护数据的完整性,也能够验证数据的来源。采用专门设计的杂凑函数的消息鉴别码是指:在设计过程中,以专门设计的杂凑函数(如SM3等)或其轮函数为主要部件,通过一定的迭代机制形成的消息鉴别码。
HMAC-SM3是一种基于专门设计的杂凑函数SM3的消息鉴别码(MAC)算法,属于MAC算法2(HMAC)的范畴。它通过将SM3杂凑函数与密钥结合,生成用于验证消息完整性和真实性的固定长度鉴别码。
1.3 基本参数
-
• 输入:
-
• 密钥K(长度不小于L2位,L2为杂凑值长度,SM3中L2=256)
-
• 消息D(长度不大于2^64-512位)
-
• 输出:固定长度的MAC值(长度m不小于32位,不大于杂凑值长度LH)
-
• 杂凑函数:SM3(符合GB/T 32905—2016标准)
-
• 安全性强度:取决于密钥长度,最高可达256位
2. 术语和定义
| 术语 | 定义 | | — | — | | 消息鉴别码(MAC) | MAC算法输出的位串,用于验证消息完整性和真实性 | | 杂凑函数 | 将任意长的位串映射为定长位串的函数,具有抗原像和抗碰撞特性 | | SM3密码杂凑算法 | 中国自主设计的专门密码学杂凑函数,输出长度为256比特 | | 轮函数 | 构成杂凑函数的主要部件,将两个特定长度的位串映射为一个定长位串 | | HMAC | 基于杂凑函数的消息鉴别码算法,通过两次杂凑函数调用实现 |
3. HMAC-SM3算法描述
3.1 通则
HMAC-SM3算法通过以下四个步骤计算MAC值:密钥扩展、杂凑操作、输出变换和截断操作。该算法需要调用两次完整的SM3杂凑函数。
3.2 算法步骤
3.2.1 步骤1:密钥扩展
- 1. 密钥预处理:
- • 若密钥K的长度大于L1位(L1为轮函数输入的第一个位串长度,SM3中L1=512),则对K进行杂凑运算,得到长度为L2位的杂凑值作为新的密钥
- • 若密钥K的长度小于L1位,则在K的右侧填充L1-k个0,得到长度为L1的位串K_padded
- • 若密钥K的长度等于L1位,则直接使用K作为K_padded
- 2. 生成子密钥:
- • IPAD:将十六进制值”36″重复L1/8次连接而成的位串(SM3中L1=512,故IPAD为64字节的”36″字符串)
- • OPAD:将十六进制值”5C”重复L1/8次连接而成的位串(SM3中L1=512,故OPAD为64字节的”5C”字符串)
- • K1 = K_padded ⊕ IPAD(内部填充密钥)
- • K2 = K_padded ⊕ OPAD(外部填充密钥)
3.2.2 步骤2:杂凑操作
将内部填充密钥K1与消息D连接,作为SM3杂凑函数的输入,得到第一次杂凑结果H’:
H' = SM3(K1 || D)
3.2.3 步骤3:输出变换
将外部填充密钥K2与步骤2的结果H’连接,作为SM3杂凑函数的输入,得到第二次杂凑结果H”:
H'' = SM3(K2 || H')
3.2.4 步骤4:截断操作
根据安全需求,取位串H”最左侧m位作为最终MAC值(m不小于32位,不大于杂凑值长度LH):
MAC = MSBm(H'')
通常情况下,m取LH/2 = 128位,以平衡安全性和效率。
3.3 算法流程示意图
+-------------------+ +-------------------+
| K_padded ⊕ IPAD = K1 | | K_padded ⊕ OPAD = K2 |
+---------+---------+ +---------+---------+
| |
| |
+---------v---------+ +---------v---------+
| K1 || D | | K2 || H' |
+---------+---------+ +---------+---------+
| |
v v
+-------------------+ +-------------------+
| SM3杂凑函数 | | SM3杂凑函数 |
+---------+---------+ +---------+---------+
| |
| +------------+
v v
+----------------------------+
| H' = SM3(K1 || D) |
+----------------------------+
|
v
+----------------------------+
| H'' = SM3(K2 || H') |
+----------------------------+
|
v
+----------------------------+
| MAC = MSBm(H'') |
+----------------------------+
4. 安全性与效率分析
4.1 安全特性
HMAC-SM3算法具有以下安全特性:
- • 抗伪造性:在不知道密钥的情况下,即使获得多个(消息,MAC)对,也难以对新消息预测其MAC值
- • 抗密钥恢复攻击:难以通过已知的(消息,MAC)对推导出密钥
- • 抗碰撞攻击:继承了SM3算法的抗碰撞特性
- • 量子安全性:在SM3是量子伪随机函数的假设下,HMAC-SM3被证明是量子安全的
4.2 安全证明
若满足以下假设,HMAC-SM3算法被证明是安全的:
- 1. 使用密钥为初始值IV的轮函数是一个强MAC算法
- 2. 迭代杂凑函数SM3是抗第二原像的
4.3 安全性强度
- • 密钥长度:建议使用256位密钥,提供最高128位的安全性强度
- • MAC长度:建议使用不小于128位的MAC长度,以抵抗生日攻击
- • 消息长度:最大支持2^64-512位的消息长度
4.4 计算复杂度
- • 轮函数调用次数:若填充后的消息包含q个分组,则HMAC-SM3需要调用q+3次轮函数
- • 预计算优化:通过预计算IV1=φ(K1, IV)和IV2=φ(K2, IV),可将轮函数调用次数降低到q+1次
- • 密钥预计算:密钥扩展步骤的结果可预计算并缓存,提高后续计算效率
4.5 实现效率
- • 软件实现:适合各种计算环境,算法结构简单,易于优化
- • 硬件实现:可通过并行化设计提高计算速度
- • 内存需求:较低,主要依赖SM3杂凑函数的内存需求
5. 应用场景
HMAC-SM3算法可广泛应用于需要消息完整性验证和真实性鉴别的场景:
- 1. 网络通信安全:
- • 用于IPSec协议中的消息完整性验证
- • 用于TLS/SSL协议中的MAC计算
- • 用于安全电子邮件中的消息认证
- 2. 数据存储安全:
- • 用于数据库中数据完整性验证
- • 用于文件系统的完整性保护
- • 用于云存储服务中的数据认证
- 3. 金融交易安全:
- • 用于电子支付系统中的交易完整性验证
- • 用于银行卡交易的MAC计算
- • 用于证券交易系统中的消息认证
- 4. 物联网安全:
- • 用于物联网设备间通信的完整性验证
- • 用于传感器数据的真实性认证
- • 用于智能家居系统中的消息鉴别
- 5. 数字签名辅助:
- • 用于基于SM2椭圆曲线密码算法的数字签名中的杂凑计算
- • 用于生成和验证数字签名的消息摘要
- 6. 实际应用案例:
- • 电子门禁系统:用于保护进出记录数据的存储完整性,防止数据篡改和伪造
- • 服务器密码机:作为商用密码产品,用于提供HMAC-SM3完整性保护服务
- • 等保三级系统:符合国家网络安全等级保护要求的信息系统中的数据完整性保护
6. 实现与测试
6.1 HMAC_SM3计算过程详解脚本
6.1.1 脚本功能与特点
工作区中提供了一个详细的HMAC-SM3计算过程脚本 HMAC_SM3计算过程详解.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from gmssl import sm3, func
defbytes_to_hex(data: bytes) -> str:
return data.hex().upper()
defprint_separator(char='=', length=80):
print(char * length)
defprint_title(title: str):
print_separator()
print(title.center(80))
print_separator()
defprint_section(title: str):
print(f"\n{'=' * 80}")
print(f" {title}")
print(f"{'=' * 80}")
defprint_subsection(title: str):
print(f"\n【{title}】")
print_separator('-', 80)
defprint_item(label: str, value: str, indent: int = 2):
spaces = ' ' * indent
print(f"{spaces}{label}: {value}")
defprint_hex_block(label: str, hex_data: str, bytes_per_line: int = 32):
print(f"\n {label}:")
for i inrange(0, len(hex_data), bytes_per_line * 2):
line = hex_data[i:i + bytes_per_line * 2]
print(f" {line}")
defhmac_sm3_detailed():
print_title("HMAC-SM3 算法详细计算过程")
print("符合 GB/T 15852.2-2024 标准 第7章 MAC算法2(HMAC)")
print_separator()
print("\n请输入密钥 (十六进制格式):")
print("示例: 00112233445566778899AABBCCDDEEFF")
key_input = input("\n密钥: ").strip().replace(' ', '').upper()
try:
key_bytes = bytes.fromhex(key_input)
except ValueError:
print("错误: 密钥格式不正确,请输入有效的十六进制字符串!")
return
print("\n请选择消息输入类型:")
print(" 1. 字符串输入")
print(" 2. 十六进制输入")
choice = input("\n请选择 (1/2): ").strip()
if choice == "1":
message_input = input("请输入消息 (字符串): ").strip()
message_bytes = message_input.encode('ascii')
message_type = "string"
elif choice == "2":
message_input = input("请输入消息 (十六进制): ").strip().replace(' ', '').upper()
try:
message_bytes = bytes.fromhex(message_input)
except ValueError:
print("错误: 消息格式不正确,请输入有效的十六进制字符串!")
return
message_type = "hex"
else:
print("错误: 无效选择!")
return
L1 = 64
L2 = 32
print_section("输入参数")
print_subsection("密钥信息")
print_item("密钥长度", f"{len(key_bytes)} 字节 ({len(key_bytes) * 8} 位)")
print_item("密钥 (十六进制)", bytes_to_hex(key_bytes))
print_subsection("消息信息")
print_item("消息长度", f"{len(message_bytes)} 字节 ({len(message_bytes) * 8} 位)")
print_item("消息输入类型", "字符串"if message_type == "string"else"十六进制")
if message_type == "string":
print_item("消息 (字符串)", message_input)
print_item("消息 (十六进制)", bytes_to_hex(message_bytes))
print_subsection("算法参数")
print_item("L1 (轮函数数据输入长度)", f"{L1} 字节 ({L1 * 8} 位)")
print_item("L2 (杂凑值长度)", f"{L2} 字节 ({L2 * 8} 位)")
print_item("IPAD值", "0x36 (二进制: 00110110)")
print_item("OPAD值", "0x5C (二进制: 01011100)")
print_section("步骤1: 密钥扩展")
print_subsection("1.1 密钥填充处理")
print("算法要求:")
print(" - 若密钥长度 k > L1,则对密钥进行杂凑运算: K' = SM3(K)")
print(" - 若密钥长度 k < L1,则在右侧填充0: K' = K || 0x00...0x00")
print(" - 若密钥长度 k = L1,则 K' = K")
iflen(key_bytes) > L1:
print(f"\n输入密钥长度: {len(key_bytes)} 字节 > L1 ({L1} 字节)")
print("执行操作: 对密钥进行SM3杂凑运算")
print("\n输入:")
print_hex_block("原始密钥 K", bytes_to_hex(key_bytes))
key_padded = bytes.fromhex(sm3.sm3_hash(func.bytes_to_list(key_bytes)))
print("\n输出:")
print_hex_block("填充后密钥 K' = SM3(K)", bytes_to_hex(key_padded))
eliflen(key_bytes) < L1:
print(f"\n输入密钥长度: {len(key_bytes)} 字节 < L1 ({L1} 字节)")
print(f"执行操作: 在密钥右侧填充 {L1 - len(key_bytes)} 个 0x00 字节")
print("\n输入:")
print_hex_block("原始密钥 K", bytes_to_hex(key_bytes))
key_padded = key_bytes + b'\x00' * (L1 - len(key_bytes))
print("\n输出:")
print_hex_block("填充后密钥 K' = K || 0x00...0x00", bytes_to_hex(key_padded))
else:
print(f"\n输入密钥长度: {len(key_bytes)} 字节 = L1 ({L1} 字节)")
print("执行操作: 无需填充")
print("\n输入/输出:")
print_hex_block("密钥 K'", bytes_to_hex(key_bytes))
key_padded = key_bytes
print_subsection("1.2 生成 IPAD 和 OPAD")
print("算法要求:")
print(" - IPAD = 0x36 重复 L1 次 (共64字节)")
print(" - OPAD = 0x5C 重复 L1 次 (共64字节)")
ipad = b'\x36' * L1
opad = b'\x5c' * L1
print("\n输出:")
print_hex_block("IPAD (0x36 × 64)", bytes_to_hex(ipad))
print_hex_block("OPAD (0x5C × 64)", bytes_to_hex(opad))
print_subsection("1.3 计算子密钥 K1 和 K2")
print("算法要求:")
print(" - K1 = K' ⊕ IPAD (按位异或)")
print(" - K2 = K' ⊕ OPAD (按位异或)")
k1 = bytes(a ^ b for a, b inzip(key_padded, ipad))
k2 = bytes(a ^ b for a, b inzip(key_padded, opad))
print("\n输入:")
print_hex_block("填充后密钥 K'", bytes_to_hex(key_padded))
print_hex_block("IPAD", bytes_to_hex(ipad))
print_hex_block("OPAD", bytes_to_hex(opad))
print("\n输出:")
print_hex_block("子密钥 K1 = K' ⊕ IPAD", bytes_to_hex(k1))
print_hex_block("子密钥 K2 = K' ⊕ OPAD", bytes_to_hex(k2))
print_section("步骤2: 杂凑操作")
print_subsection("2.1 构造第一次杂凑输入")
print("算法要求:")
print(" - 输入数据 = K1 || 消息")
h1_input = k1 + message_bytes
print("\n输入:")
print_hex_block("子密钥 K1", bytes_to_hex(k1))
print_hex_block("消息", bytes_to_hex(message_bytes))
print("\n输出:")
print_item("输入数据长度", f"{len(h1_input)} 字节 ({len(h1_input) * 8} 位)")
print_hex_block("输入数据 = K1 || 消息", bytes_to_hex(h1_input))
print_subsection("2.2 计算第一次杂凑值")
print("算法要求:")
print(" - H' = SM3(K1 || 消息)")
print("\n输入:")
print_hex_block("杂凑输入数据", bytes_to_hex(h1_input))
h1_hex = sm3.sm3_hash(func.bytes_to_list(h1_input))
h1_bytes = bytes.fromhex(h1_hex)
print("\n输出:")
print_hex_block("第一次杂凑值 H'", h1_hex.upper())
print_item("H' 长度", f"{len(h1_bytes)} 字节 ({len(h1_bytes) * 8} 位)")
print_section("步骤3: 输出变换")
print_subsection("3.1 构造第二次杂凑输入")
print("算法要求:")
print(" - 输入数据 = K2 || H'")
h2_input = k2 + h1_bytes
print("\n输入:")
print_hex_block("子密钥 K2", bytes_to_hex(k2))
print_hex_block("第一次杂凑值 H'", h1_hex.upper())
print("\n输出:")
print_item("输入数据长度", f"{len(h2_input)} 字节 ({len(h2_input) * 8} 位)")
print_hex_block("输入数据 = K2 || H'", bytes_to_hex(h2_input))
print_subsection("3.2 计算第二次杂凑值")
print("算法要求:")
print(" - H'' = SM3(K2 || H')")
print("\n输入:")
print_hex_block("杂凑输入数据", bytes_to_hex(h2_input))
h2_hex = sm3.sm3_hash(func.bytes_to_list(h2_input))
h2_bytes = bytes.fromhex(h2_hex)
print("\n输出:")
print_hex_block("第二次杂凑值 H''", h2_hex.upper())
print_item("H'' 长度", f"{len(h2_bytes)} 字节 ({len(h2_bytes) * 8} 位)")
print_section("步骤4: 截断操作")
print_subsection("4.1 MAC值长度设置")
mac_length = 128
print("算法要求:")
print(" - MAC长度 m 通常取 L2/2 = 128 位 (16 字节)")
print(f"\n设置:")
print_item("MAC长度 m", f"{mac_length} 位 = {mac_length // 8} 字节")
print_subsection("4.2 提取MAC值")
print("算法要求:")
print(" - MAC = MSB_m(H'')")
print(f" - 取 H'' 的最左侧 {mac_length} 位")
mac_hex = h2_hex[:mac_length // 4].upper()
mac_bytes = h2_bytes[:mac_length // 8]
print("\n输入:")
print_hex_block("第二次杂凑值 H''", h2_hex.upper())
print("\n输出:")
print_hex_block(f"MAC值 (前{mac_length}位)", mac_hex)
print_item("MAC长度", f"{len(mac_bytes)} 字节 ({len(mac_bytes) * 8} 位)")
print_section("最终结果")
print_subsection("计算结果汇总")
print_item("完整杂凑值 H''", h2_hex.upper())
print_item("MAC值 (128位)", mac_hex)
print_item("MAC值 (256位)", h2_hex.upper())
print_subsection("算法流程回顾")
print("HMAC-SM3 算法完整流程:")
print(" 步骤1: 密钥扩展")
print(" - K1 = K' ⊕ IPAD")
print(" - K2 = K' ⊕ OPAD")
print(" 步骤2: 杂凑操作")
print(" - H' = SM3(K1 || 消息)")
print(" 步骤3: 输出变换")
print(" - H'' = SM3(K2 || H')")
print(" 步骤4: 截断操作")
print(" - MAC = MSB_m(H'')")
print_separator()
if __name__ == "__main__":
whileTrue:
hmac_sm3_detailed()
print("\n是否继续计算? (y/n): ", end="")
continue_choice = input().strip().lower()
if continue_choice != 'y':
print("\n程序结束。")
break
print("\n")
该脚本具有以下特点:
- • 符合国家标准:严格按照GB/T 15852.2-2024标准实现HMAC-SM3算法
- • 详细步骤展示:展示完整的计算步骤,包括密钥扩展、杂凑操作、输出变换和截断操作
- • 多种输入类型:支持字符串输入和十六进制输入两种方式
- • 可视化计算过程:详细显示每一步的输入、输出和中间结果
- • 清晰的结果展示:输出完整的杂凑值和截断后的MAC值
- • 交互式操作:提供友好的命令行交互界面
6.1.2 脚本实现细节
主要依赖库:
- •
gmssl:提供SM3杂凑函数实现 - •
func:用于字节串和列表之间的转换
核心函数:
- •
bytes_to_hex:将字节串转换为十六进制字符串 - •
hmac_sm3_detailed:HMAC-SM3算法的详细计算过程实现
算法实现步骤:
- 1. 密钥扩展:处理密钥,生成K1和K2子密钥
- 2. 杂凑操作:计算SM3(K1 || 消息)得到H’
- 3. 输出变换:计算SM3(K2 || H’)得到H”
- 4. 截断操作:提取H”的前128位作为MAC值
6.1.3 脚本使用方法
- 1. 运行脚本:
python HMAC_SM3计算过程详解.py
- 2. 输入密钥:
- • 输入十六进制格式的密钥,例如:
00112233445566778899AABBCCDDEEFF
- 3. 选择消息输入类型:
- • 选项1:字符串输入
- • 选项2:十六进制输入
- 4. 查看计算结果:
- • 脚本将显示详细的计算过程,包括每一步的输入、输出和中间结果
- • 最终输出完整的杂凑值和截断后的MAC值
6.2 测试向量
6.2.1 测试环境
- • 杂凑函数:SM3
- • 密钥长度:128位
- • MAC长度:128位
- • 测试消息:表C.1中定义的9个输入位串
6.2.2 测试结果示例
密钥1:00112233445566778899AABBCCDDEEFF
| 序号 | 输入消息 | 128位MAC值 | | — | — | — | | 1 | 空位串 | C8E4E95012EB3D449B5DD0691947986E | | 2 | “a” | 5FD9F7568A24C438F14B7A22E799B068 | | 3 | “abc” | 0933617A88D312F6F9FB4B5F200E31A6 | | 4 | “messagedigest” | 9C9A22E8B5797B82CFF9BABA56893CC1 |
密钥2:0123456789ABCDEFFEDCBA9876543210
| 序号 | 输入消息 | 128位MAC值 | | — | — | — | | 1 | 空位串 | F14B797B559216B73D3816ADFB790250 | | 2 | “a” | 5BD1836B97C74F88A77BC309E77A2694 | | 3 | “abc” | 28D8A61BE67D8BF7652C4EDA7092B612 | | 4 | “messagedigest” | E0ACCC4DA77E77D135F17F5CA1EE3E60 |
7. 与其他MAC算法的比较
| 算法 | 基础原语 | 安全性强度 | 计算效率 | 实现复杂度 | 标准支持 | | — | — | — | — | — | — | | HMAC-SM3 | SM3杂凑函数 | 最高256位 | 中等 | 简单 | GB/T 15852.2—2024 | | HMAC-SHA256 | SHA-256杂凑函数 | 最高256位 | 中等 | 简单 | FIPS PUB 198-1 | | CMAC-AES | AES分组密码 | 最高256位 | 高 | 中等 | GB/T 15852.1—2020 | | GMAC | SM4分组密码 | 最高128位 | 高 | 复杂 | 商用密码算法标准 |
8. 实施建议
8.1 密钥管理
- • 密钥生成:使用密码学安全的随机数生成器生成密钥
- • 密钥长度:建议使用256位密钥,提供最高安全性
- • 密钥更新:定期更新密钥,避免长期使用同一密钥
- • 密钥存储:采用安全的密钥存储机制,防止密钥泄露
- • 密钥传输:确保密钥在传输过程中的机密性和完整性
- • 敏感数据清除:在使用完毕后立即清除内存中的密钥和敏感中间结果
8.2 实现注意事项
- • 杂凑函数实现:确保SM3杂凑函数的正确实现,可使用经过认证的实现库
- • 填充操作:严格按照标准要求执行密钥填充和消息填充
- • 截断长度:根据安全需求选择合适的MAC长度,建议不小于128位
- • 抗侧信道攻击:在硬件实现中考虑抗侧信道攻击措施
- • 密钥预处理:支持可变长度密钥,添加密钥预处理逻辑(当密钥超长时先进行哈希)
- • 防重放机制:添加防重放保护,如使用时间戳、序列号等
8.3 验证与测试
- • 正确性验证:使用标准测试向量验证实现的正确性
- • 性能测试:根据应用场景测试算法性能
- • 安全性评估:定期进行安全性评估,及时修复漏洞
- • 代码审计:对实现代码进行安全审计,检查潜在的安全问题
8.4 实际实现案例
8.4.1 基于密码服务接口的HMAC-SM3实现
// 假设已经获得了会话句柄hSessionHandle
intMAC(void *hSessionHandle, const unsigned char *key, const unsigned char *message,
unsigned int messageLen, unsigned char *mac) {
unsignedchar K_pad[64] = {0}; // 密钥填充缓冲区
unsignedchar ipad[64], opad[64]; // 内部和外部填充
unsignedchar innerHash[32]; // 内层哈希结果
unsignedint hashLen = 32; // SM3输出长度
int i;
// 步骤1:密钥填充处理
memcpy(K_pad, key, 32); // 复制32字节密钥到64字节缓冲区
// 步骤2:生成内部和外部填充
for (i = 0; i < 64; i++) {
ipad[i] = K_pad[i] ^ 0x36; // 内部填充:异或0x36
opad[i] = K_pad[i] ^ 0x5c; // 外部填充:异或0x5c
}
// 步骤3:计算内层哈希 H(ipad || message)
SDF_HashInit(hSessionHandle, 0x00000001, NULL, NULL, 0); // 初始化SM3算法
SDF_HashUpdate(hSessionHandle, ipad, 64); // 添加内部填充
SDF_HashUpdate(hSessionHandle, message, messageLen); // 添加消息
SDF_HashFinal(hSessionHandle, innerHash, &hashLen); // 获得内层哈希
// 步骤4:计算外层哈希 H(opad || innerHash)
SDF_HashInit(hSessionHandle, 0x00000001, NULL, NULL, 0); // 重新初始化
SDF_HashUpdate(hSessionHandle, opad, 64); // 添加外部填充
SDF_HashUpdate(hSessionHandle, innerHash, 32); // 添加内层哈希
SDF_HashFinal(hSessionHandle, mac, &hashLen); // 获得最终MAC值
return0;
}
8.4.2 关键实现说明
- 1. HMAC结构:严格遵循RFC2104标准实现
- • 内层哈希:H(K_ipad || message)
- • 外层哈希:H(K_opad || 内层哈希结果)
- 2. 安全特性:
- • 密钥处理:通过固定长度填充(64字节)和异或操作消除密钥长度差异
- • 双重哈希:有效防止长度扩展攻击
- • 使用经过认证的密码服务接口(SDF_*函数)
- 3. 算法标识:
- • 0x00000001:表示使用SM3算法(输出32字节)
8.5 常见安全问题与最佳实践
8.5.1 常见安全问题
- 1. 密钥管理问题:
- • 密钥明文传输,未进行机密性和完整性保护
- • 敏感数据未清除,残留在内存中
- • 密钥长度不足或使用弱密钥
- 2. 实现问题:
- • 未添加防重放机制,容易遭受重放攻击
- • 消息格式设计不合理,无法防止篡改
- • 未使用链式完整性保护,无法检测记录删除或插入
- 3. 部署问题:
- • 密钥长期不更新
- • 未定期进行安全性评估
- • 缺乏监控和审计机制
8.5.2 最佳实践
- 1. 链式完整性保护:
- • 每条记录的MAC值作为下一条记录的输入,形成密码学链条
- • 防止记录被删除、插入或重新排序
- 2. 防重放机制:
- • 使用时间戳+随机数确保每条消息唯一
- • 添加消息序列号,防止重复处理
- 3. 合规性考虑:
- • 遵循等保要求,使用经过认证的密码产品
- • 定期进行密码应用安全性评估
- • 建立完善的密钥管理体系
- 4. 数据库设计最佳实践:
- • 添加integrity_type字段,明确标注使用的算法
- • 添加msg_serial_no字段,实现防重放
- • 添加prev_log_hash字段,实现链式完整性
- • 分离敏感字段,采用不同的保护机制
9. 总结
HMAC-SM3算法是基于中国自主设计的SM3杂凑函数的消息鉴别码算法,具有高安全性、高效率和良好的实现特性。该算法通过两次SM3杂凑函数调用,结合密钥生成固定长度的MAC值,可有效用于消息完整性验证和真实性鉴别。
作为国家标准GB/T 15852.2—2024的重要组成部分,HMAC-SM3算法在网络通信、数据存储、金融交易和物联网等领域具有广泛的应用前景。随着中国商用密码体系的不断完善,HMAC-SM3算法将在保障国家信息安全方面发挥越来越重要的作用。
9.1 技术优势
- • 自主可控:基于中国自主设计的SM3杂凑函数,具有自主知识产权
- • 高安全性:提供最高256位的安全性强度,能够抵抗各种已知攻击
- • 高效率:算法结构简单,易于实现和优化
- • 广泛适用性:可应用于各种计算环境和应用场景
- • 标准支持:符合国家标准,便于跨系统互操作
9.2 发展趋势
- • 硬件加速:随着物联网和5G技术的发展,硬件加速实现将成为趋势
- • 量子安全:算法设计考虑了量子安全特性,能够抵抗量子计算攻击
- • 轻量级实现:针对资源受限设备的轻量级实现将得到更多关注
- • 标准化应用:在更多国家标准和行业标准中得到应用
HMAC-SM3算法作为基于杂凑函数的消息鉴别码算法的重要代表,将在未来的网络安全领域中继续发挥重要作用,为数字经济的发展提供坚实的安全保障。
参考文献
- 1. GB/T 15852.2—2024《网络安全技术 消息鉴别码 第2部分:采用专门设计的杂凑函数的机制》
- 2. GB/T 32905—2016《信息安全技术 SM3密码杂凑算法》
- 3. GB/T 18238.3—2024《网络安全技术 杂凑函数 第3部分:专门设计的杂凑函数》
- 4. FIPS PUB 198-1《The Keyed-Hash Message Authentication Code (HMAC)》
- 5. ISO/IEC 10118-3《Information technology—Security techniques—Hash-functions—Part 3: Dedicated hash-functions》
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:利刃信安 利刃信安 利刃信安《【密码算法】HMAC-SM3 消息鉴别码》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论