Skip to content

响应加密

NullVerify 支持对客户端 API 的响应内容进行加密,防止中间人窃取业务数据。

支持的算法

算法密钥来源密文格式安全性
rc4 (默认)独立加密密钥base64(cipher)低,仅防简单抓包
aes-cbc独立加密密钥base64(iv).base64(cipher)中,推荐对称方案
des-cbc独立加密密钥base64(iv).base64(cipher)低,仅兼容旧系统
rsa开发者上传 RSA 公钥base64(rsaKey).base64(iv).base64(cipher)高,推荐非对称方案

加密算法必选

创建应用时默认使用 RC4 加密,所有应用必须选择一种加密算法,不支持关闭加密。

配置方式

在管理后台 → 应用配置 → 安全配置 中选择响应加密算法。

  • 对称加密(RC4 / AES-CBC / DES-CBC):系统自动生成独立加密密钥,可在安全配置页查看和重新生成。
  • RSA 混合加密:需上传 RSA 公钥(PEM 格式,≥ 2048 位)。

注意

修改加密配置后,所有客户端必须同步更新解密逻辑,否则将无法解析响应。建议先在测试环境验证后再上线。

加密流程

启用响应加密后,原始的业务 JSON 响应会被整体加密,并包装在新的 JSON 结构中返回:

json
// 未加密(原始业务响应)
{
  "code": 0,
  "message": "ok",
  "result": { "token": "abc123", "expires": "2026-12-31 23:59:59" }
}

// 加密后(以 AES-CBC 为例)
{
  "code": 200,
  "message": "ok",
  "encrypted": true,
  "data": {
    "ciphertext": "dGhpcyBpcyBpdi4=.Y2lwaGVydGV4dC4="
  }
}

勘误说明

外层包装结构的 code(固定 200)和 message 是明文占位,不代表业务状态。客户端收到响应后,需先判断 encrypted 是否为 true,然后解密 data.ciphertext,从解密后的 JSON 中读取实际的业务 codemessageresult

客户端解密

解密步骤

  1. 判断是否加密:检查响应 JSON 的 encrypted 字段是否为 true
  2. 提取密文:获取 data.ciphertext 字段值。
  3. 执行解密:根据算法规则解密密文字符串,得到明文 JSON。
  4. 解析业务响应:将明文解析为 JSON 对象,从中读取实际的 codemessageresult

对称加密(RC4 / AES-CBC / DES-CBC)

密钥获取:在管理后台 → 应用配置 → 安全配置 中查看独立加密密钥(64 字符 hex 字符串)。

客户端需将 hex 密钥解码为字节数组,并按算法取指定长度前缀作为实际密钥:

key = hex_decode(encrypt_key)[:keyLen]
算法keyLen(字节)
rc416
aes-cbc32
des-cbc8

RC4 解密

python
import base64

def get_key(encrypt_key_hex: str, length: int) -> bytes:
    return bytes.fromhex(encrypt_key_hex)[:length]

def rc4_decrypt(key: bytes, ciphertext_b64: str) -> str:
    data = base64.b64decode(ciphertext_b64)
    # RC4 加解密逻辑相同
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    out = bytearray(len(data))
    i = j = 0
    for k in range(len(data)):
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        out[k] = data[k] ^ S[(S[i] + S[j]) % 256]
    return out.decode('utf-8')

# 使用:encrypt_key 从管理后台安全配置页获取
# ciphertext_field 从响应的 data.ciphertext 获取
key = get_key("your_encrypt_key_hex", 16)
plaintext = rc4_decrypt(key, ciphertext_field)

AES-CBC 解密

密文格式:base64(iv).base64(ciphertext),使用 . 分隔。

python
import base64
from Crypto.Cipher import AES

def aes_cbc_decrypt(key: bytes, encrypted: str) -> str:
    parts = encrypted.split(".")
    iv = base64.b64decode(parts[0])
    ciphertext = base64.b64decode(parts[1])
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded = cipher.decrypt(ciphertext)
    # PKCS#7 去填充
    pad_len = padded[-1]
    return padded[:-pad_len].decode('utf-8')

key = get_key("your_encrypt_key_hex", 32)
# ciphertext_field 从响应的 data.ciphertext 获取
plaintext = aes_cbc_decrypt(key, ciphertext_field)

DES-CBC 解密

密文格式与 AES-CBC 相同:base64(iv).base64(ciphertext)

python
from Crypto.Cipher import DES

key = get_key("your_encrypt_key_hex", 8)
# 解密逻辑同 AES-CBC,替换为 DES.new(key, DES.MODE_CBC, iv)

RSA 混合加密解密

密文格式:base64(rsaEncryptedKey).base64(iv).base64(ciphertext),使用 . 分隔为 3 段。

解密流程:

  1. 用私钥通过 RSA-OAEP (SHA-256) 解密第一段,得到 AES-256 密钥
  2. 用该 AES 密钥 + IV(第二段)通过 AES-CBC 解密第三段
  3. 去除 PKCS#7 填充
python
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
from Crypto.Hash import SHA256
import base64

def rsa_hybrid_decrypt(private_key_pem: str, encrypted: str) -> str:
    parts = encrypted.split(".")
    enc_key = base64.b64decode(parts[0])
    iv = base64.b64decode(parts[1])
    ciphertext = base64.b64decode(parts[2])

    # RSA-OAEP 解密 AES key
    rsa_key = RSA.import_key(private_key_pem)
    cipher_rsa = PKCS1_OAEP.new(rsa_key, hashAlgo=SHA256)
    aes_key = cipher_rsa.decrypt(enc_key)

    # AES-CBC 解密数据
    cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv)
    padded = cipher_aes.decrypt(ciphertext)
    pad_len = padded[-1]
    return padded[:-pad_len].decode('utf-8')

RSA 公钥要求

  • 格式:PEM(-----BEGIN PUBLIC KEY-----
  • 最小位数:2048 位
  • 上传后系统自动计算 SHA-256 指纹用于标识

算法选择建议

场景推荐算法原因
快速接入、低安全需求rc4实现简单,性能最好
通用场景aes-cbc安全性与性能平衡
兼容旧系统des-cbc仅在旧系统无法升级时使用
高安全需求rsa密钥不暴露在客户端,最安全
对应实现
  • 加密逻辑: pkg/crypto/response_encrypt.go
  • 响应中间件: internal/platform/httpx/response.go

面向脚本与插件开发者的网络验证系统