前言
这个问题是一个个例,不具备普适性,但为啥仍然拿出来呢?
主要还是想和大家分享一个排查问题的思路的方式,一步一步的缩小问题范围,最终确定问题所在。
最近在做一个生僻字相关的需求:对接生僻字键盘,支持输入生僻字,并完成生僻字传输,落库,查询,反显等一系列动作。
对接生僻字键盘上的工作倒是不复杂,结果问题出在了生僻字传输这一步上。
部分生僻字通过国密加密后到服务端解密显示就是 ?了,这也直接导致落库后的内容是一个错乱字符,反显自然也有问题
分析原因
阶段一
梳理整个数据传输流程:
初步判断,与加解密有关
- 尝试明文传输生僻字字符串到后端,落库,反显一切正常
- 尝试对生僻字字符进行 Unicode 转换,再进行加密传输,后端解密,落库,查询后通过 Unicode 还原,反显一切正常
这两步试验明确了原生僻字字符直接进行国密加密后会导致后端解密失败,文字变成 ?
同组的小伙伴排查到这里之后,选择直接使用第二种尝试进行业务实现,就是转 Unicode 的方案。
这样虽然可以解决当前的问题,但是也意味着所有需要显示生僻字的渠道场景,都需要做 Unicode 字符解析的动作才能正常展示这些字段,牵扯的系统比较多,改造成本也比较大。
阶段二
后来我接手了这个问题,在这个基础上提出了一个新的问题: 那为啥只有部分生僻字会出现这种情况呢?
初步判断,这些加解密失败的生僻字的原字符编码比较特殊,可能国密加密库的实现对其支持不到位
查阅了一些关于文字编码的资料后,尤其是阮一峰老师的《Unicode与JavaScript详解》后,豁然开朗
- 尝试针对这些加解密失败的生僻字进行 Unicode 还原,发现这些生僻字都是 4 字节的,而那些 2 字节的生僻字通过加解密后可以正常显示
- 尝试更换国密加密库进行尝试,发现可以进行正常的加解密显示
原本打算直接更换三方的国密库,奈何金融系统对源码要求高,所以还是需要使用自研的这套sm4加密库。
不过已经定位到是因为 4 字节生僻字导致的加密后乱码的原因,直接对接研发中心负责加密库的团队申请源码,发现果然是不同字节字符加密处理时,唯独没有支持 4 字节的字符转换,导致加解密异常了。
更换新的 sm4 加密库后,问题终于得到解决!
后记
这个问题,总的来说也算是公司自研加解密库的一个缺陷,生僻字的字符加密没有考虑全面,不过一步一步抽丝剥茧下来分析问题的过程,还是想记录下来以作分享,希望大家分析一些问题时可以有一些启发和参考。