Skip to main content

Python 常用内置模块

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}")

安全注意事项

  1. 密钥管理:确保密钥安全存储,不要硬编码在源代码中
  2. 算法选择:推荐使用 SHA256 或更强的哈希算法,避免使用 MD5
  3. 时间攻击防护:使用 hmac.compare_digest() 进行安全比较
  4. 密钥长度:密钥长度应该至少等于哈希函数的输出长度
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、文件校验、密码存储等场景中都有广泛应用。