前段时间工作的内容中涉及到传输数据的加密,加密方式是AES+RSA,具体过程中也参考了一些网上的文章,简单写一个记录。
加密的原理这里就不具体说了,网上可以查到各种文章,这里简单说一下实现的逻辑。首先AES为对称加密,加密解密用同一个密钥,RSA为非对称加密,加密解密过程需要使用到一个公钥和一个私钥。
我们项目中的逻辑是这样的:首先客户端需要用到的有客户端私钥和服务器公钥。
第一步首先对数据进行签名。取出字典中数据的所有value,转换成字符串格式然后进行拼接,然后使用客户端的私钥进行签名,得到签名字符串,然后以加入到原始数据的字典里。之后将这个新的添加了签名的字典转换成json格式的字符串,便得到需要加密的数据。这里要注意的是,验签成功的条件是,最终传输的json字符串中的数据需要和和你签名的value字符串顺序一致,当然忽略签名数据。
这里有一个坑。我在实现这部分功能的时候,为了保持顺序一致,先按照key给数据进行了排序,取这个顺序的value进行拼接并签名,然后使用如下方式整个数据进行转json字符串。

这时候,iOS 11和以后的版本和之前的版本得到的结果的顺序是不一样的。iOS 11以后的顺序和按照key排序得到的顺序是一致的,而iOS 11之前的版本是另一个固定的顺序,这就导致直接使用这个数据的话iOS 11之前的版本会验签失败。处理这种情况,我的思路有两种,一是换一种转json的方式,自己写一个转json的逻辑自己控制顺序,二是转换出字符串之后把取出各个key的位置,排个序,按这个顺序重新拼一下value,签名,之后替换掉原来的签名。
得到了数据之后,客户端本地生成一个随机字符串作为AES密钥,然后使用该密钥对数据进行加密得到加密之后的数据1,再使用服务器公钥对AES密钥进行加密,得到加密之后的数据2,给服务器传输这两个数据。
接收返回的数据时,先用客户端私钥对返回数据的数据2进行解密,取得AES密钥,再使用该密钥对数据1进行解密得到返回数据。
简单的Demo传送门https://github.com/AllenMu/LJYAES-RSA
有任何问题欢迎指正
网友评论