在微信公众号支付分账场景中,接收方信息包含姓名、银行卡号、身份证号等高度敏感字段。如果直接以明文形式写入数据库,一旦遭遇拖库或内部越权访问,就会导致大范围隐私泄露与资金风险。采用AES加密对敏感接收方信息进行存储,是当前多数合规系统的标准做法。AES属于对称加密,加密和解密使用同一密钥,运算效率高,适合频繁读写的业务系统。

为什么分账接收方信息必须加密
微信公众号支付分账允许商户将交易资金按比例结算给多个接收方,这些接收方可能是个人也可以是入驻商户。个人接收方提交的开户名、卡号、证件号在监管口径下均属于个人金融信息,受个人信息保护法与支付行业安全规范约束。若系统仅依赖网络传输层的HTTPS,数据在服务端落盘后依旧是明文,等于把风险留给了数据库层和运维人员。
实际案例中,不少中小商户使用开源分账系统,默认配置将接收方资料原样存进用户表。黑客通过弱口令进入后台即可批量导出,引发诈骗与盗刷。加密存储让即便拿到数据库文件的人也无法还原真实卡号,把数据价值降到最低,也满足了等保与微信支付商户准入的技术评审要求。
AES算法模式与密钥选择
AES本身只是分组密码,需要配合模式使用。常见的CBC模式要额外做填充且易受 padding oracle 攻击,不建议在新系统中采用。更优选择是GCM模式,它同时提供加密和完整性校验,能防止密文被篡改。密钥长度推荐128位或256位,256位安全性更高但部分旧环境支持有限,按合规等级取舍即可。
密钥绝不能写在代码配置里或前端包中。正确方式是将主密钥存放在云厂商的密钥管理服务,或自建硬件加密机。应用服务器启动时通过鉴权接口获取数据密钥,内存中使用后及时清理。这样即使代码仓库公开,攻击者也无法解密历史数据,实现密钥与数据的分离保护。
敏感字段加密存储实现步骤
第一步,在接收方信息提交接口处,后端收到姓名、卡号等字段后立刻调用加密函数。以Java为例,使用AES_GCM算法,随机生成十二字节IV,输出密文与IV一起用Base64编码。第二步,数据库表中对应列类型改用TEXT或BLOB,只保存密文与IV,原始明文不落库。第三步,查询时如需展示,在有权限控制的后台做解密,并脱敏显示如仅留卡号后四位。
需要注意,加密字段无法像明文那样直接做模糊查询或排序。系统设计时应把用作检索的接收方编号单独留明文或哈希值,敏感内容仅作为详情字段。此外,定期轮换数据密钥,用旧密钥解密再在新密钥下重加密,可进一步压缩密钥泄露影响窗口。
加密前后存储结构对比
下面用一张表说明接收方表在加密改造前后的差异,帮助理解字段层面的变化。
| 字段名 | 改造前存储 | 改造后存储 |
|---|---|---|
| receiver_name | 张三 | Base64密文 |
| bank_card | 6222021234567890123 | Base64密文加IV |
| id_number | 110105199001011234 | Base64密文加IV |
| receiver_no | R202405001 | 同左,用于检索 |
常见错误与规避办法
一种典型错误是多个接收方复用同一个IV,这会让相同明文产出相同密文,容易被推测规律。必须每次加密生成随机IV并随密文保存。另一种错误是把密钥和密文备份在同一压缩包,等于没加密。备份时应分开存储,密钥库开启访问控制与审计日志。
还有团队为了便于排查,在日志里打印解密后的接收方信息,这直接破坏了加密意义。正确做法是日志只记脱敏后与业务号,真实敏感值仅在受限服务内内存处理。把这些细节写进开发规范,分账系统的数据安全才算真正落地。