最近在对接第三方的开放接口。对方的规矩是:请求体用 AES 加密,AES 密钥再用平台 RSA 公钥加密后一起发过去。
标准的 hybrid 方案,看着没难度。结果联调花的时间比写业务代码还多。三个坑,全都栽在「同一个名词、双方理解不一样」上。
坑一:Base64 密文里的 + 变成了空格
我把密文直接塞进表单 body,本地测试全通过,上了环境却偶发失败。抓包才看到 a+b/c= 里的 + 变成空格了。
原因是 application/x-www-form-urlencoded 会把 + 解码成空格。密文是随机字节,平均几十个字符就撞上一次,所以它表现为「偶发」------最烦的那种 bug。
改用 JSON body 提交,一次性解决。
坑二:RSA 的 padding 文档里没写
文档只写了「RSA 加密」四个字。我按推荐的安全实践用了 OAEPWithSHA-256AndMGF1Padding,对方解不开;换回 PKCS1Padding 才通。
这里有个连带知识点:padding 不同,单次能加密的明文上限也不同。2048 位密钥下,PKCS1 是 117 字节,OAEP(SHA-256) 只剩约 62 字节。这也是为什么长报文必须用混合加密------RSA 本身扛不住。
坑三:getBytes() 偷用了默认字符集
content.getBytes() 不传参,就用系统默认值。我本机 UTF-8 一切正常,部署到 GBK 默认的测试机后,中文姓名全线乱码。更阴的是解密流程本身「成功」了,日志一个报错都没有。
现在一律显式指定:
ini
byte[] plain = content.getBytes(StandardCharsets.UTF_8);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
一句话经验
加解密的算法实现几乎不会写错,真正吃时间的是传输编码、填充模式、字符编码这三层------恰恰是文档里最常被省略的部分。下次再对接加密接口,我会先把这三项列成清单让对方逐条确认,再写第一行代码。
你们对接第三方加密接口时踩过什么坑?评论区聊聊。