Table of Contents

18.11 服务端解密流程

当前服务端按以下顺序处理,其他语言服务若实现同协议也必须保持失败关闭:

  1. 判断是否为 /tieup/api/v1/**,并在读取 body 前排除握手、上传、回调和 OPTIONS
  2. 根据 APP 版本头或 H5 环境变量解析加密策略;未知 APP 版本返回 4609
  3. 判断 GET 是否存在 e,或写请求 Content-Type 是否为加密类型;强制模式下明文返回 4606
  4. 校验 X-Device-IdX-Session-Id 及 Redis Session 绑定关系。
  5. 用最终方法、URI path 和客户端上下文构造 AAD。
  6. Base64URL 解码外层信封和 n/c/t,校验版本、IV 和 Tag 长度。
  7. 使用 Session Key 执行 AES-256-GCM 认证解密;任何密文、Tag 或 AAD 篡改返回 4606
  8. 校验时间戳、request ID、nonce 和 data,通过 Redis 原子消费 nonce。
  9. GET 使用 withQueryParams(data);写请求使用 withParsedBody(data) 并恢复 JSON body/Content-Type。
  10. 将重写后的请求写回请求上下文,再交给验证、鉴权和 Controller。

PHP 密码核心等价代码:

$plaintext = openssl_decrypt(
    $ciphertext,
    'aes-256-gcm',
    $sessionKeyRaw,
    OPENSSL_RAW_DATA,
    $iv,
    $tag,
    $aad
);

if ($plaintext === false) {
    throw new BusinessException(ResultCode::API_ENCRYPTION_PAYLOAD_INVALID);
}

不得记录握手密钥、Session Key、解密后的敏感业务参数或完整密文。策略缓存只保存数据库中的密钥封装值,不能缓存明文版本密钥。