1 : 背景
项目采用的架构是SpringBoot + Vue构建。
加密方式采用RSA + AES 双重加密。
1、前端调用后端接口,获取RSA公钥。
2、前端把公钥加密,加密串调用接口传后端,后端解密保存redis。
3、前端调用后端接口,后端通过AES对密钥加盐,然后通过RSA对数据加密,返回前端。
整个过程中一直都是没有问题的,直到有一天,页面突然报错:
IOException: DerInputStream.getLength(): lengthTag=106, too big.
2 : 分析原因
在该问题暴发前,系统并未进行发布。
集群服务器,仅有部分服务器有问题,其他暂无问题。
以此判定为偶发事情。
那么既然是偶发,但是在运行的过程中,一直都是
IOException: DerInputStream.getLength(): lengthTag=106, too big.
结合代码发现redis有存该密钥。
排查代码:
找到了请求方式的不同,在前端传后端RSA加密密钥的代码中,请求的加密串,是通过拼接在url后面的方式传到后端的。
测试环境发现,将数据放在请求后面,某些加密串中的特殊符号会自动转换为空
比如**=**,就会转换成空串,导致后端保存的密钥与前端提供的并不对等。
3 : 总结
将请求的参数放在body中传,而不放在请求后面传参,解决了该问题。
网上查阅资料,发现并不仅仅是特殊符号会替换,例如 %2B 等,也会替换,所以,放在请求body里面还是最保险的。