Skip to content

服务端 API 签名加密

前言

本方案为平台应用(APP)服务端SUD OP SVR 之间的接口通信提供一套完整的鉴权体系,采用数据加密+数字签名的双重安全机制,有效防止接口数据在传输过程中被泄漏、篡改,同时具备操作行为的不可否认性。平台应用(APP)服务端可在 SUD OpenPaaS 管理后台的「API安全模块」完成密钥、公钥的配置与管理,以此保障服务端与 SUD OP SVR 之间接口交互的安全性。

一、核心概念解释

1.1 服务签名与验签

平台应用服务端调用 SUD OpenPaaS API(如获取用户信息、登录鉴权等)时,需通过自身应用私钥生成请求签名(支持 RSA、SM2 两种签名算法);SUD OP SVR 接收请求后,通过平台应用配置的应用公钥完成签名验签,验证请求的真实性与数据完整性。

SUD OP SVR 向平台应用服务端发起回调时,平台应用需通过SUD OpenPaaS 证书中的公钥完成回调验签,验证平台回调的真实性。

核心名词定义

  • 应用公钥:平台应用通过 SUD OpenPaaS 管理后台在线生成,保存在 API 安全配置中,用于 SUD OP SVR 对平台应用的接口调用进行验签。
  • 应用私钥:平台应用通过 SUD OpenPaaS 管理后台生成并下载,仅由平台应用服务端自行保管,用于生成接口请求的数字签名,需严格保障其安全性。
  • SUD OpenPaaS证书:包含 SUD OpenPaaS 公钥信息的官方证书,平台应用用于验证 SUD OP SVR 接口回包/回调的签名,在配置应用公钥后可从 API 安全模块下载。

1.2 接口内容加密

SUD OP SVR 支持对接口请求内容响应内容采用 AES256/SM4 算法加密,加密后接口报文以密文形式在网络中传输,大幅提升数据传输安全性。

加密与签名的执行顺序:应用方需先对请求明文进行加密得到密文,再对密文生成数字签名,禁止先签名后加密。

二、密钥配置说明

平台应用服务端需在 SUD OpenPaaS 管理后台完成对称密钥非对称密钥对的在线生成与配置,并下载SUD OpenPaaS证书

2.1 进入API安全配置页

平台应用服务端登录 SUD OpenPaaS 管理后台后,进入「API安全配置」页面进行操作。

2.2 配置接口内容加密对称密钥

对称密钥用于接口请求/响应内容的加解密,支持 AES256、SM4 两种算法:

  • 需在 API 安全配置页点击生成对称密钥,系统将生成 43 个字符的标准 Base64 字符串(解码后长度32);
  • 配置完成后可下载密钥(仅可下载一次),需本地妥善保管。

2.3 配置应用非对称密钥对

非对称密钥对用于接口请求的签名与验签,支持 RSA、SM2 两种算法:

  • 需在 API 安全配置页在线生成应用非对称密钥对(生成后,应用公钥将自动保存在管理后台中);
  • 密钥对生成完成后,必须立即下载应用私钥(仅可下载一次),下载后需在应用服务端严格做好保密措施。

2.4 获取 SUD OpenPaaS 证书

应用密钥配置完成后,可在 API 安全配置页下载 SUD OpenPaaS 证书,同时可查看已配置密钥的编号(SN)与基础信息。

三、API请求处理规范

平台应用启用接口加密与签名后,需按照以下规范处理 API 请求:先对请求明文加密生成密文,再对密文生成签名,最终将加密参数签名信息标准请求头一同发送至 SUD OP SVR

3.1 请求明文加密(AES256_GCM/SM4_GCM)

3.1.1 加密后请求参数要求

  • 请求参数

    参数必填备注
    iv初始向量,Base64编码后为16字节字符串(解码后为12字节随机数据)
    data加密后的请求密文,Base64编码
    authtagGCM分组模式输出的认证信息,用于验证密文完整性,Base64编码
  • GCM模式额外认证数据(AAD)

    需设置 额外认证数据(AAD) 对密文进行认证,统一规定 AAD 格式为:urlpath|appid|timestamp|sn(各字段用竖线 | 分隔)

    字段说明
    urlpath当前请求API的URL路径,包含URL协议信息,不包括URL参数(URL Query)。
    appid平台应用的唯一标识 AppId
    timestamp加密操作的时间戳(秒级),需与请求头 X-Sud-Timestamp 的值完全一致
    sn本次加密使用的对称密钥编号,从API安全配置页获取
  • 请求明文格式要求

    待加密的请求明文需采用JSON格式,包含原 API 的所有参数,并强制添加三个安全字段

    参数类型必填备注
    data原类型原API要求的所有参数,不包含AccessToken
    _nstring防重放随机字符串(Nonce),推荐使用16-32字节的Base64随机字符串
    _appidstring平台应用的唯一标识 AppId,必须与AAD中的 appid 一致
    _timestampnumber加密操作的时间戳(秒级),必须与AAD中的 timestamp 一致

3.1.2 计算示例

以下示例以 AES256_GCM 算法为例,演示一次完整的请求加密过程。

  • 准备密钥与上下文信息

    • 请求路径 (urlpath): https://api.sud.com/v1/game/login
    • 对称密钥编号 (sn): key_v1
    • 对称密钥内容 (key): otUpngOjU+nVQaWJIC3D/yMLV17RKaP6t4Ot9tbnzLY=
    • 当前时间戳 (timestamp): 1710500000
    • 应用ID (appid): app_10010
  • 准备原始业务数据

    json
    {
        "appid": "app_10010",
        "sud_uid": "user_889900",
        "scene": 0,
        "client_ip": "127.0.0.1"
    }
  • 生成 IV 并拼接 AAD

    生成 12 字节随机数据,并进行 Base64 编码作为 iv

    text
    base64_encode(iv) = fmW/zNxXlytUZBgj

    按照 urlpath|appid|timestamp|sn 格式严格拼接 AAD:

    text
    aad = https://api.sud.com/v1/game/login|app_10010|1710500000|key_v1
  • 组装最终待加密明文 (补齐安全字段)

    json
    {
        "_n": "o89QaPVsRu1yppIZzvSZc4",
        "appid": "app_10010",
        "sud_uid": "user_889900",
        "scene": 0,
        "client_ip": "127.0.0.1",
        "_appid": "app_10010",
        "_timestamp": 1710500000
    }
  • 压缩 JSON 并执行加密

    将上述 JSON 压缩为无多余空格和换行的字符串(作为实际的 plaintext):

    json
    {"_n":"o89QaPVsRu1yppIZzvSZc4","_appid":"app_10010","_timestamp":1710500000,"appid":"app_10010","sud_uid":"user_889900","scene":0,"client_ip":"127.0.0.1"}

    传入 plaintextkeyivaad 执行 AES256_GCM 加密,分别提取密文和认证标签并 Base64 编码:

    text
    base64_encode(enc_data) = OIDVdrPtSPF/0e2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1C
    base64_encode(authtag) = 5qeM/2vZv+6KtScN94IpMg==
  • 最终作为 HTTP Body 的请求密文

    json
    {
        "iv": "fmW/zNxXlytUZBgj",
        "data": "OIDVdrPtSPF/0e2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1C",
        "authtag": "5qeM/2vZv+6KtScN94IpMg=="
    }

3.2 加密请求的数字签名

3.2.1 参数说明

  • 请求参数

    在 API 请求中,平台应用服务端需通过自身私钥对请求内容生成签名,并通过 HTTP Header 传递给 SUD OP SVR。

    Header名必填描述
    X-Sud-AppId平台应用填写的 AppId
    X-Sud-Timestamp签名时的时间戳(秒级),必须与加密时的一致
    X-Sud-Signature签名串(Base64 编码)
  • 待签名串(String-to-Sign)拼接规范

    为了彻底消除验签时的换行符歧义,待签名串严格遵循以下拼接公式: String-to-Sign = urlpath + "\n" + appid + "\n" + timestamp + "\n" + data

    参与签名的参数说明
    urlpath当前请求API的URL,不包括URL参数(URL Query),需要带HTTP协议头。
    appid当前调用的 AppId(即 X-Sud-AppId 的值)。
    timestamp签名时的时间戳(即 X-Sud-Timestamp 的值)。
    dataHTTP 请求的 Body 原始字符串,即 3.1.2 最终生成的 JSON 字符串(若请求无 Body,此项为空。

    注意:SM2withSM3 签名算法需要用到的 ID 默认为平台应用非对称密钥编号(SN)。

3.2.2 计算示例

接续 3.1.2 的加密结果,我们对登录鉴权接口的请求数据进行签名。

  • 私钥信息 (RSAwithSHA256 - PSS填充方式)

    注:PSS 签名中包含随机因子 (salt length=32),因此即使原文相同,每次计算出的签名结果也会不同,这是安全且正常的。

    json
    {
        "Sn": "rsa_key_v1",
        "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA3F0Q0m015/CF...\n-----END RSA PRIVATE KEY-----"
    }
  • 拼接待签名串 M

    按照规范,将各部分用 \n 连接。

    text
    https://api.sud.com/v1/game/login
    app_10010
    1710500000
    {"iv":"fmW/zNxXlytUZBgj","data":"OIDVdrPtSPF/0e2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1C","authtag":"5qeM/2vZv+6KtScN94IpMg=="}
  • 计算签名并编码

    对上述字符串 M 使用应用私钥进行签名:

    text
    base64_encode(Signature) = wcSSWHZunjz9VKl9q+If9deiyECXDAELFAJNZ4+5T+NhFr8zfhkwdQtlgQ7nM...
  • 最终发送的完整 HTTP 请求

    http
    POST /v1/game/login HTTP/1.1
    Host: api.sud.com
    Content-Type: application/json; charset=utf-8
    X-Sud-AppId: app_10010
    X-Sud-Timestamp: 1710500000
    X-Sud-Signature: wcSSWHZunjz9VKl9q+If9deiyECXDAELFAJNZ4+5T+NhFr8zfhkwdQtlgQ7nM...
    
    {"iv":"fmW/zNxXlytUZBgj","data":"OIDVdrPtSPF/0e2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1C","authtag":"5qeM/2vZv+6KtScN94IpMg=="}

四、API响应处理规范

SUD OP SVR 返回的响应数据均为密文+签名形式,平台应用需按照先验签、后解密的顺序处理响应数据。

4.1 响应数据验签

4.1.1 验签相关响应头要求

响应头名必填备注
X-Sud-AppId平台应用的 AppId,与请求头的 X-Sud-AppId 一致
X-Sud-TimestampSUD OP SVR 生成响应的时间戳(秒级)
X-Sud-SerialSUD OpenPaaS证书编号
X-Sud-SignatureSUD OP SVR的响应签名结果,Base64编码
X-Sud-Serial-Deprecated即将失效的证书编号(证书轮换期返回)
X-Sud-Signature-Deprecated即将失效的平台证书签名数据,使用base64编码(证书轮换期返回)

4.1.2 待验签串拼接规则

为保证签名框架的一致性,SUD OP SVR 响应的待验签串与请求签名规则完全相同: String-to-Verify = urlpath + "\n" + appid + "\n" + timestamp + "\n" + data

参与验签的参数说明
urlpath当前请求API的URL,不包括URL参数(URL Query),需要带HTTP协议头。
appid响应头 X-Sud-AppId 的值。
timestamp响应头 X-Sud-Timestamp 的值。
dataHTTP 响应的 Body 原始密文字符串。

4.2 响应密文解密

解密使用的对称密钥密钥编号与应用方请求时一致。AAD 拼接格式为 urlpath|appid|timestamp|sn。解密后同样需要强校验明文中的 _appid_timestamp

五、常见错误码及解决方案

错误码错误码取值解决方案
40231API_Missing_Sud_AppId请求头缺失:缺少 X-Sud-AppId 字段。请检查 HTTP Header 是否正确注入了平台应用的唯一标识 AppId。
40232API_Missing_Sud_Timestamp请求头缺失:缺少 X-Sud-Timestamp 字段。请补充秒级时间戳,并确保其与加密报文内部的 _timestamp 完全一致。
40233API_Missing_Sud_Signature请求头缺失:缺少 X-Sud-Signature 字段。请检查私钥签名逻辑,并将生成的签名进行 Base64 编码后放入该 Header。
40234API_Invalid_Signature签名验证失败(高频):1. 检查当前使用的应用私钥是否与 SUD OpenPaaS 管理后台配置的公钥成对。
40235API_Invalid_Encrypt加解密失败:1. 检查 AES_GCM 的 AAD 拼接格式(urlpath|appid|timestamp|sn)是否正确。2. 确认传入的 Cipher 密文是否完整。在部分语言底层库中,需要将加密输出的 CipherText 与 AuthTag 拼接后传递;若分离输出,需确保 JSON 报文中的 authtag 字段无误。
40236API_Invalid_Sud_AppIdAppId 无效或未生效:平台无法识别 X-Sud-AppId。请核对 AppId 拼写,或确认该应用在 SUD OpenPaaS 后台的状态是否为正常启用。
40237API_Request_Expired请求已过期(防重放拦截):请求头中的 X-Sud-Timestamp 与服务器当前时间的误差超过了允许的阈值(通常为 5 分钟),或者报文内部的 _n (Nonce) 已被使用过。请确保业务服务器开启了 NTP 时间同步。

六、生产环境安全架构最佳实践(必读)

  1. 强防重放机制(Replay Attack Protection): 服务端接收到任何请求后,必须严格校验时间戳 timestamp,如果与系统当前时间差值超过 300 秒(5分钟),直接拒绝。对于 300 秒内的请求,必须将解密出的 _n (Nonce) 结合 _appid 存入 Redis 等分布式缓存中(TTL 设置为 300 秒)。任何新请求在处理前,若在 Redis 中命中相同的 Nonce,视为重放攻击直接阻断。
  2. 私钥绝对隔离与备份: 应用私钥、对称密钥属于最高级别凭证,严禁硬编码在代码或配置文件中。由于管理后台生成的私钥仅可下载一次,研发团队必须建立安全的内网 KMS 系统或密文配置中心进行托管与备份。
  3. 平台证书平滑轮转: 当检测到响应头包含 X-Sud-Serial-Deprecated 时,说明 SUD OpenPaaS 平台正在进行证书更替轮转。应用系统应触发告警或自动化脚本,及时拉取最新的平台证书。
  4. 应用密钥无缝切换(规划中规范): 若 APP 方发生私钥泄露疑虑需更换密钥,为避免业务中断,建议在请求时可携带 X-Sud-App-Serial 请求头指定密钥版本(视 SUD 平台具体版本支持情况而定),以实现灰度平滑切换。

七、示例代码

  1. nodejs
  2. java
  3. golang
  4. python
  5. php