API 接口签名算法 SHA256 如何防止参数篡改确保鉴权安全?

文章导读
单纯使用 SHA256 哈希并不能防止篡改,必须结合密钥使用 HMAC-SHA256 算法,并在服务端进行签名比对,适用于所有涉及敏感数据交互的 API 场景。
📋 目录
  1. 核心签名代码实现(Python)
  2. 服务端验签逻辑
  3. 使用 curl 验证签名生效
  4. 常见工程坑点
  5. 参考来源
A A

单纯使用 SHA256 哈希并不能防止篡改,必须结合密钥使用 HMAC-SHA256 算法,并在服务端进行签名比对,适用于所有涉及敏感数据交互的 API 场景。

先说结论:API 签名安全的核心不在于哈希算法本身,而在于密钥保管和签名生成规则,单纯哈希无法抵御重放和篡改。

  • 先判断:确认业务是否必须使用签名,内部可信网络可简化,公开接口必须签名。
  • 优先做:实施 HMAC-SHA256 而非裸 SHA256,确保密钥不出服务端。
  • 再验证:通过修改请求参数测试签名是否失效,确认防篡改机制生效。

核心签名代码实现(Python)

以下是通用的签名生成逻辑,可直接参照实现。关键在于参数排序和 HMAC 计算,替代原有的文本步骤:

import hmac
import hashlib
import urllib.parse

def generate_sign(params, secret_key):
    # 1. 过滤掉 sign 字段本身
    filtered_params = {k: v for k, v in params.items() if k != 'sign'}
    # 2. 按参数名 ASCII 码从小到大排序
    sorted_params = sorted(filtered_params.items())
    # 3. 拼接成 key1=value1&key2=value2 格式
    query_string = urllib.parse.urlencode(sorted_params)
    # 4. 拼接密钥
    string_to_sign = query_string + secret_key
    # 5. HMAC-SHA256 计算
    signature = hmac.new(
        secret_key.encode('utf-8'),
        string_to_sign.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    # 6. 转为大写(根据接口规范决定)
    return signature.upper()

服务端验签逻辑

服务端收到请求后,需使用相同算法计算签名并与客户端传入的签名比对。注意使用恒定时间比较防止时序攻击:

def verify_sign(request_params, received_sign, secret_key):
    # 重新计算签名
    calculated_sign = generate_sign(request_params, secret_key)
    # 恒定时间比较
    return hmac.compare_digest(calculated_sign, received_sign.lower())

使用 curl 验证签名生效

通过 curl 命令模拟请求,验证篡改参数后签名是否失效。假设接口地址为 http://api.example.com/data,密钥为 my_secret

API 接口签名算法 SHA256 如何防止参数篡改确保鉴权安全?

1. 发送正常请求(签名正确):

curl -X GET "http://api.example.com/data?app_id=1001×tamp=1715623400&sign=8A7B...C3D2"
# 预期返回:200 OK 或业务成功数据

2. 篡改参数验证(签名错误):

修改 app_id 但保持原签名不变,服务端应拒绝:

curl -X GET "http://api.example.com/data?app_id=1002×tamp=1715623400&sign=8A7B...C3D2"
# 预期返回:401 Unauthorized 或 签名无效错误

常见工程坑点

  • 密钥泄露:密钥写在客户端代码中会被反编译获取,仅适用于服务端间调用。移动端建议使用 OAuth 或短期 Token。
  • 参数顺序不一致:不同语言对字典序实现可能不同,需明确指定排序规则(如 ASCII 码)。
  • URL 编码差异:空格是编码为 + 还是 %20,两端逻辑必须统一,建议统一使用 urlencode 标准库。
  • 重放攻击:仅靠签名无法防止重放,必须配合时间戳校验(如±5 分钟)和 nonce 缓存机制。

参考来源

  • RFC 2104 - HMAC: Keyed-Hashing for Message Authentication, https://www.rfc-editor.org/rfc/rfc2104.txt
  • NIST Special Publication 800-107 - Recommendation for Applications Using Approved Hash Algorithms, https://csrc.nist.gov/publications/detail/sp/800-107/final