主题
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 属于国密算法,部分标准库不内置:
| 语言 | 可用实现 |
|---|---|
| Python | cryptography(较新版本内置 algorithms.SM4)、gmssl |
| Java | Bouncy Castle(SM4Engine + GCMBlockCipher) |
| Node.js | OpenSSL 3.x 提供 sm4-gcm(需确认发行版编译选项),或使用 gm-crypto 等库 |
| Go | github.com/tjfoc/gmsm/sm4 配合 GCM 模式 |
联调时先验证算法可用性
接入前先用一段已知的 IV / 密文 / Tag 在目标语言里跑通解密, 再切换订单的 output_encryption。否则很容易把「依赖不支持 SM4」 误判成「平台返回了错误数据」。
何时启用
| 情况 | 建议 |
|---|---|
| 传输全程已走 HTTPS(TLS),且回调接收端在自己内网 | NONE 即可 |
| 回调要经过第三方网关,或日志系统会把报文写进磁盘 | SM4 |
| 合规要求业务数据在应用层加密 | SM4 |
启用与否是每个订单的选择,写在创建授权的请求体里,并且参与 重复请求的比对 —— 同一订单号不能中途改变。