写在前面的话:
之前一篇文章《Creator WebSocket Protobuf整合之保姆级全攻略》大概的介绍了下有关protobuf的整合,首先我们认清一点protobuf仅仅是数据封装的模式,并没有加密功能,简单的来说将其理解成增强型json,以便于理解。
近期也看了一些服务器端的源码,总的来说protobuf算是比较主流的,老点的项目有用json的或者是body是json然后用LengthField加头的。不管如何我个人还是建议使用protobuf,其优势不再赘述了。
在阅读源码期间,偶然发现baidu的开源项目 [jprotobuf] (https://github.com/jhunters/jprotobuf) ,其主要的优势就是不需要再编写.proto的文件的直接在pojo类上加上注解即可,一定程度的简化了我们开发的流程提高的开发效率。但我个人观点还是需要.proto文件的,即便没有此文件也需要通过文档的形式列出所有通讯消息的结构体。随时时间的推移项目的迭代以及各种跨平台的客户端的开发,有一份清晰的文档往往事半功倍,这也算是我个人的偏执吧。
本文重点:
websocket/socket网路通讯主流的加密方式,适用于各种应用包括游戏。
数据的加密解密必然会带来额外的开销,至于是否采用加密取决于数据的敏感性,如果涉及用户隐私,如个人信息,交易记录等信息还是有必要的。
时序图
流程解释
1.客户端创建连接(建立websocket/socket通讯),申请AES密钥。
1).当连接创建成功后客户端所发出去的第一个包是通过RSA公钥加密的,其目的就是为了和服务器端申请后续通讯所使用的AES密钥。
2.而服务器当收到客户端的请求AES密钥的请求包时
1).通过RSA私钥解密请求包,并验证消息
2).为本次连接临时生成一个AES密钥(缓存在服务器端)并返回给客户端。也就是说AES密钥每次都会变的,而不是一个固定的值。
3.客户端获取AES密钥并缓存,好了此时针对本次的连接,客户端/服务器端均有AES密钥,
那么后续的通讯数据均通过这个AES密钥进行加密解密。
*截止到这里整个通讯的加密解密过程就说完了,整理清楚了通讯流程下面的工作就会轻松许多。上面有一些关键词需要稍微了解一下,如不清楚请自行百度。以下规范一下加密算法的各项参数,具体的视项目情况而定。
规范约定
1.RSA,密钥长度1024, 填充方式PKCS1,公钥加密,私钥解密,公钥可通过私钥生成
2.AES使用AES/ECB/PKCS7Padding
RSA加密
RSA加密规则:若密钥位数是key_size, 单次加密串的最大长度为 (key_size)/8 - 11, 目前位数1024, 则最大加密长度为117,为了方便这里我们选择一次加密长度为100
将明文数据分成一个或数个最长100字节的小段进行加密,拼接分段加密数据即为最终的Body加密数据
RSA解密
RSA解密同样遵循分段规则,对于1024位密钥, 每小段待解密数据长度为128字节
将密文数据分成一个或数个128字节长的小段进行解密,拼接分段解密数据即为最终的Body解密数据
AES加密
AES加密要求源数据长度必须是16的整数倍, 故需补‘0’对齐后再加密,记录modlen为源数据长度与16取模值
因加密前有可能对源数据作修改, 故需在加密后的数据尾再增加一个16字节的填充数据块,其最后一个字节赋modlen, 其余字节赋值‘0’, 将加密数据和额外的填充数据块拼接作为最终要发送协议的body数据
AES解密
协议body数据, 先将最后一个字节取出,记录modlen, 然后将body截掉尾部16字节填充数据块后再解密(与加密填充额外数据块逻辑对应)
modlen 为0时,上述解密后的数据即为协议返回的body数据, 否则需截掉尾部(16 - 录modlen)长度的用于填充对齐的数据