Skip to content

签名验证纵深防御全景(强算法绑定 / 规范化 / 抗重放 / 业务账本闭环) ​

防御目标 ​

针对支付回调、JWT、API 鉴权、Webhook、Cookie 与下载链接等签名验证场景,建立从“输入解析 → 规范化 → 算法锁定 → 密钥隔离 → 恒定时间比较 → 抗重放与账本幂等”的闭环防御,杜绝降级、类型混淆、长度扩展与重放绕过。

六维纵深防御矩阵 ​

攻击维度核心漏洞根因强制防御标准对应专题防御
算法降级 / 混淆信任请求自带 alg / sign_type 或公钥混用为 HMAC 密钥服务端按 kid/路由硬编码唯一算法白名单,密钥对象绑定用途01-algorithm-defense
验证实现缺陷== 宽松比较、未校验参数类型(数组/null)、异常捕获返回通过强制类型校验 + 恒定时间比较(hmac.compare_digest)+ 默认拒绝02-implementation-defense
密钥泄露与弱熵默认密钥、前端/源码泄露、短密码可爆破256-bit CSPRNG 密钥、KMS/HSM 托管、定期轮换与环境隔离03-key-attacks-defense
规范化差异验签层与业务层使用不同解析器或未剔除重复/空白/编码歧义先严格反序列化并校验唯一键,再对同一规范对象做签名校验04-canonicalization-defense
长度扩展攻击使用 MD5(secret + msg) / SHA256(secret + msg) 裸拼接全面迁移至 HMAC-SHA256、KMAC 或 Ed2551905-length-extension-defense
重放与并发竞态无 nonce/过期窗口过宽、非原子查重或缺失账本幂等键原子 SET NX EX 去重 + 严格时间窗 + 数据库唯一事务锁06-replay-nonce-defense

统一安全验签管线实现(Python) ​

将规范化、算法锁定、时间窗、原子去重与恒定时间比对封装为不可绕过的单一验证入口:

python
import hashlib
import hmac
import json
import time

class StrictSignatureVerifier:
    def __init__(self, key_store: dict[str, bytes], max_skew_sec: int = 300):
        self.key_store = key_store
        self.max_skew_sec = max_skew_sec
        self.used_nonces: set[str] = set()

    def canonicalize(self, payload: dict) -> bytes:
        # 严格类型与字段校验,采用 RFC 8785 风格紧凑排序 JSON
        return json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")

    def verify(self, key_id: str, alg: str, ts: int, nonce: str, sig_hex: str, payload: dict, now: int | None = None) -> tuple[bool, str]:
        if alg != "HMAC-SHA256":
            return False, "disallowed_algorithm"
        if not isinstance(sig_hex, str) or len(sig_hex) != 64:
            return False, "invalid_signature_format"
        if not isinstance(nonce, str) or len(nonce) < 16:
            return False, "invalid_nonce"
        key = self.key_store.get(key_id)
        if not key or len(key) < 32:
            return False, "unknown_or_weak_key"

        cur = int(time.time()) if now is None else now
        if abs(cur - ts) > self.max_skew_sec:
            return False, "timestamp_out_of_window"
        nonce_key = f"{key_id}:{nonce}"
        if nonce_key in self.used_nonces:
            return False, "replay_nonce_rejected"

        signing_input = f"{ts}.{nonce}.".encode("utf-8") + self.canonicalize(payload)
        expected = hmac.new(key, signing_input, hashlib.sha256).hexdigest()
        if not hmac.compare_digest(sig_hex.lower(), expected):
            return False, "signature_mismatch"

        self.used_nonces.add(nonce_key)
        return True, "verified"

if __name__ == "__main__":
    key = b"k" * 32
    v = StrictSignatureVerifier({"v1": key})
    body = {"order_id": "ORD-1001", "amount": 9900}
    ts, nonce = 1700000000, "9f86d081884c7d659a2feaa0c55ad015"
    msg = f"{ts}.{nonce}.".encode() + v.canonicalize(body)
    sig = hmac.new(key, msg, hashlib.sha256).hexdigest()
    assert v.verify("v1", "HMAC-SHA256", ts, nonce, sig, body, now=ts)[0] is True
    assert v.verify("v1", "none", ts, nonce, sig, body, now=ts) == (False, "disallowed_algorithm")
    assert v.verify("v1", "HMAC-SHA256", ts, nonce, sig, body, now=ts) == (False, "replay_nonce_rejected")
    print("signature_overview_defense: PASS")

防御工作流 ​

text
1. 边界收口:将签名验证统一收口到独立中间件,禁止业务 handler 自行读取未验签原始参数
2. 算法与密钥锁定:服务端按 kid 从密钥库检索预期算法与密钥,忽略客户端传递的 alg/sign_type
3. 规范化与类型检查:拒绝重复参数(HPP)、数组型签名及非法编码,保证验签对象与业务对象完全一致
4. 恒定时间比对与默认拒绝:使用安全对比函数,任何异常分支一律返回 401/403
5. 账本幂等闭环:验签后结合订单号/事务 ID 在数据库行锁内完成金额核对与状态推进

验证与判定标准 ​

  • 全维度阴性用例:注入 alg=none、空签名、数组类型签名、过期时间戳、重复 nonce 与篡改金额,全部返回拒绝且账本状态零变更
  • 密钥强度达标:所有 HMAC 密钥长度 >= 32 字节(256 bit),且未出现在代码仓库或前端静态资源中
  • 单一解析一致:签名验证函数直接向下游业务返回解析后的强类型结构体,消除解析差异

MCP 工具映射 ​

防御环节MCP 工具用途
分域防御文档检索kb_router快速定位算法、实现、密钥或重放专题防御文档
加固验证用例落盘workspace_write_text保存统一验签中间件与回归测试套件
异常签名告警规则make_sigma_stub生成针对高频 alg=none 与重放失败事件的 WAF/日志规则

Apache-2.0 · 仅供授权环境下的学习与防御性研究使用 · 免责声明