Python 内置模块 hmac
HMAC(Hash-based Message Authentication Code,基于哈希的消息认证码)是一种用于验证消息完整性和真实性的密码学技术。它结合了密钥和哈希函数,确保消息在传输过程中没有被篡改,并且来源可信。Python 的 hmac 模块提供了 HMAC 算法的实现,是标准库的一部分,无需额外安装。
基本用法
创建 HMAC 对象
import hmac
import hashlib
# 使用密钥和消息创建 HMAC
key = b'secret_key'
message = b'Hello, World!'
# 创建 HMAC 对象,默认使用 MD5
h = hmac.new(key, message, hashlib.md5)
print(f"HMAC (MD5): {h.hexdigest()}")
# 指定哈希算法为 SHA256
h_sha256 = hmac.new(key, message, hashlib.sha256)
print(f"HMAC (SHA256): {h_sha256.hexdigest()}")
使用字符串作为输入
import hmac
import hashlib
# 字符串需要编码为字节
key = 'my_secret_key'.encode('utf-8')
message = '这是一条中文消息'.encode('utf-8')
h = hmac.new(key, message, hashlib.sha256)
print(f"中文消息的 HMAC: {h.hexdigest()}")
更新 HMAC 内容
HMAC 对象支持增量更新,适用于处理大文件或流数据:
import hmac
import hashlib
key = b'incremental_key'
# 创建空的 HMAC 对象
h = hmac.new(key, digestmod=hashlib.sha256)
# 分批添加数据
h.update(b'First part of ')
h.update(b'the message.')
print(f"增量 HMAC: {h.hexdigest()}")
# 与一次性计算结果相同
h_direct = hmac.new(key, b'First part of the message.', hashlib.sha256)
print(f"直接计算 HMAC: {h_direct.hexdigest()}")
print(f"结果相同: {h.hexdigest() == h_direct.hexdigest()}")
不同的哈希算法
import hmac
import hashlib
key = b'algorithm_test'
message = b'Testing different algorithms'
# 支持的常用哈希算法
algorithms = [
('MD5', hashlib.md5),
('SHA1', hashlib.sha1),
('SHA256', hashlib.sha256),
('SHA512', hashlib.sha512)
]
for name, algo in algorithms:
h = hmac.new(key, message, algo)
print(f"{name}: {h.hexdigest()}")
HMAC 验证
安全比较函数
import hmac
import hashlib
def verify_message(key, message, expected_hmac):
"""安全地验证消息的 HMAC"""
calculated_hmac = hmac.new(key, message, hashlib.sha256).hexdigest()
# 使用 compare_digest 防止时间攻击
return hmac.compare_digest(calculated_hmac, expected_hmac)
# 示例验证
key = b'verification_key'
original_message = b'Important data'
# 生成 HMAC
original_hmac = hmac.new(key, original_message, hashlib.sha256).hexdigest()
print(f"原始 HMAC: {original_hmac}")
# 验证正确的消息
is_valid = verify_message(key, original_message, original_hmac)
print(f"验证结果: {is_valid}")
# 验证被篡改的消息
tampered_message = b'Important data modified'
is_valid_tampered = verify_message(key, tampered_message, original_hmac)
print(f"篡改消息验证结果: {is_valid_tampered}")
获取不同格式的输出
import hmac
import hashlib
import base64
key = b'output_format_key'
message = b'Format testing message'
h = hmac.new(key, message, hashlib.sha256)
# 十六进制格式(最常用)
hex_digest = h.hexdigest()
print(f"十六进制: {hex_digest}")
# 二进制格式
binary_digest = h.digest()
print(f"二进制长度: {len(binary_digest)} 字节")
# Base64 编码格式
b64_digest = base64.b64encode(binary_digest).decode('utf-8')
print(f"Base64: {b64_digest}")
# 注意:调用 digest() 或 hexdigest() 后不能再更新
print(f"摘要长度: {h.digest_size} 字节")
print(f"算法名称: {h.name}")
复制 HMAC 对象
import hmac
import hashlib
key = b'copy_test_key'
# 创建原始 HMAC 对象
original = hmac.new(key, b'Initial data', hashlib.sha256)
# 复制对象
copied = original.copy()
# 对复制的对象进行不同的更新
original.update(b' - Original')
copied.update(b' - Copied')
print(f"原始对象 HMAC: {original.hexdigest()}")
print(f"复制对象 HMAC: {copied.hexdigest()}")
文件 HMAC 计算
import hmac
import hashlib
def calculate_file_hmac(file_path, key):
"""计算文件的 HMAC"""
h = hmac.new(key, digestmod=hashlib.sha256)
try:
with open(file_path, 'rb') as f:
# 分块读取文件,适用于大文件
while chunk := f.read(8192):
h.update(chunk)
return h.hexdigest()
except FileNotFoundError:
return None
# 示例:创建临时文件并计算 HMAC
import tempfile
import os
key = b'file_hmac_key'
# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
temp_file.write('这是一个测试文件的内容\n包含多行文本')
temp_path = temp_file.name
# 计算文件 HMAC
file_hmac = calculate_file_hmac(temp_path, key)
print(f"文件 HMAC: {file_hmac}")
# 清理临时文件
os.unlink(temp_path)
常见应用场景
API 签名验证
import hmac
import hashlib
import time
def generate_api_signature(api_key, request_data, timestamp):
"""生成 API 请求签名"""
# 构造待签名字符串
sign_string = f"{request_data}|{timestamp}"
signature = hmac.new(
api_key.encode('utf-8'),
sign_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
# 模拟 API 调用
api_key = "your_api_secret"
request_data = "user_id=123&action=transfer&amount=100"
current_time = str(int(time.time()))
signature = generate_api_signature(api_key, request_data, current_time)
print(f"API 签名: {signature}")
# 服务器端验证(模拟)
def verify_api_signature(api_key, request_data, timestamp, received_signature):
expected_signature = generate_api_signature(api_key, request_data, timestamp)
return hmac.compare_digest(expected_signature, received_signature)
# 验证签名
is_valid = verify_api_signature(api_key, request_data, current_time, signature)
print(f"签名验证结果: {is_valid}")
安全注意事项
- 密钥管理:确保密钥安全存储,不要硬编码在源代码中
- 算法选择:推荐使用 SHA256 或更强的哈希算法,避免使用 MD5
- 时间攻击防护:使用
hmac.compare_digest()
进行安全比较 - 密钥长度:密钥长度应该至少等于哈希函数的输出长度
import hmac
import hashlib
import secrets
# 生成安全的随机密钥
def generate_secure_key(length=32):
"""生成指定长度的安全随机密钥"""
return secrets.token_bytes(length)
# 示例
secure_key = generate_secure_key()
message = b'Secure message'
# 使用强哈希算法
secure_hmac = hmac.new(secure_key, message, hashlib.sha256)
print(f"安全 HMAC: {secure_hmac.hexdigest()}")
# 演示不安全的比较(仅作教学用途)
def unsafe_compare(a, b):
"""不安全的比较方式"""
return a == b
# 安全的比较方式
hmac1 = hmac.new(secure_key, b'message1', hashlib.sha256).hexdigest()
hmac2 = hmac.new(secure_key, b'message2', hashlib.sha256).hexdigest()
print(f"使用 compare_digest: {hmac.compare_digest(hmac1, hmac2)}")
本章节详细讲解了 Python hmac
模块的基本用法和高级特性。HMAC 是确保数据完整性和认证的重要工具,在 Web API、文件校验、密码存储等场景中都有广泛应用。