服务端 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编码 authtag 是 GCM分组模式输出的认证信息,用于验证密文完整性,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 _n string 是 防重放随机字符串(Nonce),推荐使用16-32字节的Base64随机字符串 _appid string 是 平台应用的唯一标识 AppId,必须与AAD中的 appid 一致 _timestamp number 是 加密操作的时间戳(秒级),必须与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
- 请求路径 (urlpath):
准备原始业务数据
json{ "appid": "app_10010", "sud_uid": "user_889900", "scene": 0, "client_ip": "127.0.0.1" }生成 IV 并拼接 AAD
生成 12 字节随机数据,并进行 Base64 编码作为
iv:textbase64_encode(iv) = fmW/zNxXlytUZBgj按照
urlpath|appid|timestamp|sn格式严格拼接 AAD:textaad = 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"}传入
plaintext、key、iv、aad执行 AES256_GCM 加密,分别提取密文和认证标签并 Base64 编码:textbase64_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的值)。data HTTP 请求的 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连接。texthttps://api.sud.com/v1/game/login app_10010 1710500000 {"iv":"fmW/zNxXlytUZBgj","data":"OIDVdrPtSPF/0e2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1C","authtag":"5qeM/2vZv+6KtScN94IpMg=="}计算签名并编码
对上述字符串 M 使用应用私钥进行签名:
textbase64_encode(Signature) = wcSSWHZunjz9VKl9q+If9deiyECXDAELFAJNZ4+5T+NhFr8zfhkwdQtlgQ7nM...最终发送的完整 HTTP 请求
httpPOST /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-Timestamp | 是 | SUD OP SVR 生成响应的时间戳(秒级) |
| X-Sud-Serial | 是 | SUD OpenPaaS证书编号 |
| X-Sud-Signature | 是 | SUD 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 的值。 |
| data | HTTP 响应的 Body 原始密文字符串。 |
4.2 响应密文解密
解密使用的对称密钥、密钥编号与应用方请求时一致。AAD 拼接格式为 urlpath|appid|timestamp|sn。解密后同样需要强校验明文中的 _appid 与 _timestamp。
五、常见错误码及解决方案
| 错误码 | 错误码取值 | 解决方案 |
|---|---|---|
| 40231 | API_Missing_Sud_AppId | 请求头缺失:缺少 X-Sud-AppId 字段。请检查 HTTP Header 是否正确注入了平台应用的唯一标识 AppId。 |
| 40232 | API_Missing_Sud_Timestamp | 请求头缺失:缺少 X-Sud-Timestamp 字段。请补充秒级时间戳,并确保其与加密报文内部的 _timestamp 完全一致。 |
| 40233 | API_Missing_Sud_Signature | 请求头缺失:缺少 X-Sud-Signature 字段。请检查私钥签名逻辑,并将生成的签名进行 Base64 编码后放入该 Header。 |
| 40234 | API_Invalid_Signature | 签名验证失败(高频):1. 检查当前使用的应用私钥是否与 SUD OpenPaaS 管理后台配置的公钥成对。 |
| 40235 | API_Invalid_Encrypt | 加解密失败:1. 检查 AES_GCM 的 AAD 拼接格式(urlpath|appid|timestamp|sn)是否正确。2. 确认传入的 Cipher 密文是否完整。在部分语言底层库中,需要将加密输出的 CipherText 与 AuthTag 拼接后传递;若分离输出,需确保 JSON 报文中的 authtag 字段无误。 |
| 40236 | API_Invalid_Sud_AppId | AppId 无效或未生效:平台无法识别 X-Sud-AppId。请核对 AppId 拼写,或确认该应用在 SUD OpenPaaS 后台的状态是否为正常启用。 |
| 40237 | API_Request_Expired | 请求已过期(防重放拦截):请求头中的 X-Sud-Timestamp 与服务器当前时间的误差超过了允许的阈值(通常为 5 分钟),或者报文内部的 _n (Nonce) 已被使用过。请确保业务服务器开启了 NTP 时间同步。 |
六、生产环境安全架构最佳实践(必读)
- 强防重放机制(Replay Attack Protection): 服务端接收到任何请求后,必须严格校验时间戳
timestamp,如果与系统当前时间差值超过 300 秒(5分钟),直接拒绝。对于 300 秒内的请求,必须将解密出的_n(Nonce) 结合_appid存入 Redis 等分布式缓存中(TTL 设置为 300 秒)。任何新请求在处理前,若在 Redis 中命中相同的 Nonce,视为重放攻击直接阻断。 - 私钥绝对隔离与备份: 应用私钥、对称密钥属于最高级别凭证,严禁硬编码在代码或配置文件中。由于管理后台生成的私钥仅可下载一次,研发团队必须建立安全的内网 KMS 系统或密文配置中心进行托管与备份。
- 平台证书平滑轮转: 当检测到响应头包含
X-Sud-Serial-Deprecated时,说明 SUD OpenPaaS 平台正在进行证书更替轮转。应用系统应触发告警或自动化脚本,及时拉取最新的平台证书。 - 应用密钥无缝切换(规划中规范): 若 APP 方发生私钥泄露疑虑需更换密钥,为避免业务中断,建议在请求时可携带
X-Sud-App-Serial请求头指定密钥版本(视 SUD 平台具体版本支持情况而定),以实现灰度平滑切换。