Skip to content

SM4 输出加密

创建授权时传入 output_encryption: "SM4",可以让平台把发给你的 JSON 内容整体加密, 再装进一个固定结构里返回 —— 这个装着密文的固定结构就是下文的「SM4-GCM 信封」。

影响范围

报文是否加密
回调通知 Body
订单查询 / 产品查询成功响应
V1 数据接口成功响应
V2 发票 JSON 接口成功响应
错误响应(4xx / 5xx,业务码失败)❌ 保持明文
PDF 文件、授权协议、HTML 页面
Worker 原始表格文件
发票压缩分片

错误始终明文

错误响应不加密,是为了让客户在密钥配置出错时仍能定位参数与鉴权问题。

信封结构

json
{
  "encrypted": true,
  "algorithm": "SM4-GCM",
  "version": "tax-rpa.sm4-gcm.v1",
  "encoding": "BASE64",
  "keyDerivation": "SHA256_CALLBACK_SECRET_FIRST_16_BYTES",
  "iv": "Base64 编码的 12 字节随机 IV",
  "ciphertext": "Base64 编码的 JSON 密文",
  "tag": "Base64 编码的 16 字节认证标签"
}

密钥派生

text
key = SHA-256(callback_secret 的 UTF-8 字节)[0:16]

固定取 SHA-256 结果的前 16 字节作为 SM4 密钥。

明文是 UTF-8 JSON,序列化时使用紧凑分隔符并按对象键排序 —— 这一点只影响平台侧的确定性输出,客户端解密后正常解析即可。

解密

先验证签名,再解密

回调场景必须先对收到的原始密文信封完成 X-RPA-Signature 签名验证, 再执行 SM4-GCM 解密。顺序颠倒等于对来路不明的数据做解密运算。

解密时应先校验 GCM Tag,再解析 JSON。

Python

python
import base64
import hashlib
import json

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes


def decrypt_envelope(envelope: dict, callback_secret: str) -> dict:
    key = hashlib.sha256(callback_secret.encode("utf-8")).digest()[:16]
    decryptor = Cipher(
        algorithms.SM4(key),
        modes.GCM(
            base64.b64decode(envelope["iv"]),
            base64.b64decode(envelope["tag"]),
        ),
    ).decryptor()
    plain = decryptor.update(base64.b64decode(envelope["ciphertext"]))
    plain += decryptor.finalize()          # Tag 校验失败会在这里抛异常
    return json.loads(plain.decode("utf-8"))

统一入口

建议在 HTTP 客户端里包一层,业务代码不感知加密开关:

python
def unwrap(body: dict, callback_secret: str) -> dict:
    if isinstance(body, dict) and body.get("encrypted") is True:
        return decrypt_envelope(body, callback_secret)
    return body

依赖

SM4 属于国密算法,部分标准库不内置:

语言可用实现
Pythoncryptography(较新版本内置 algorithms.SM4)、gmssl
JavaBouncy Castle(SM4Engine + GCMBlockCipher
Node.jsOpenSSL 3.x 提供 sm4-gcm(需确认发行版编译选项),或使用 gm-crypto 等库
Gogithub.com/tjfoc/gmsm/sm4 配合 GCM 模式

联调时先验证算法可用性

接入前先用一段已知的 IV / 密文 / Tag 在目标语言里跑通解密, 再切换订单的 output_encryption。否则很容易把「依赖不支持 SM4」 误判成「平台返回了错误数据」。

何时启用

情况建议
传输全程已走 HTTPS(TLS),且回调接收端在自己内网NONE 即可
回调要经过第三方网关,或日志系统会把报文写进磁盘SM4
合规要求业务数据在应用层加密SM4

启用与否是每个订单的选择,写在创建授权的请求体里,并且参与 重复请求的比对 —— 同一订单号不能中途改变。

适配平台 1.5.3 · 接入指南、接口参考、字段字典与税局状态统一入口。