相对安全的网络传输方案

最近做一个C端的项目,需要设计一个“相对”安全的传输方案,用于确保数据在传输过程中的安全。
首先提到安全传输第一个想到的自然是走HTTPS,复习一下HTTPS为什么安全:

https
简单说下,https讲解网上一大堆:
1.客户端和服务器建立连接
2.服务器发送公钥给客户端
3.客户端用公钥加密数据后发给服务器
4.服务器用私钥进行数据解密
5.其中为了防止公钥被劫持,又引入了CA
6.CA是一家被信任的第三个机构,负责发布数字证书来保证公钥不被篡改
7.客户端发请求时,服务器把CA给的数字证书给客户端
8.客户端通过CA提供的公钥获取数字签名,来确保证书安全

如果将数据传输分为三大部分:服务器、传输中、落到客户端。那么HTTPS其实只是保护传输中的数据安全而已。
也就是在传输过程中第三方抓的包是密文的。
那么在服务器和客户端抓的包自然是明文,这就是为什么有些新手测试会说为什么能抓到明文的包,因为他们的测试方法都是在客户端抓包,数据已经落到客户端解密,自然能抓到。
服务器抓包不讨论,如果有在服务器抓包的能力那么跟任何的“传输”方案没关系,找运维比较靠谱。
客户端抓包很常见,尤其是现在的Android开放程度比较高,或者APP使用PC的代理,然后PC抓包。

所以需要设计一个针对客户端抓包方案:

步骤5和7当时画的不准确,以下面文字描述为准

总体思路:
1.每个APP或者终端,发送请求到负责授权的服务,授权服务根据终端唯一特性,比如IMEI、MAC等特征信息为该终端生成RSA密钥对,然后把公钥返回。
2.APP可以将公钥存在内存里
3.由于RSA的非对称加解密特性导致在大数据量的情况下加解密都特别的慢,所以这边要引入对称加密AES,简单来说RSA是非对称加密,也就是公钥加密,私钥解密。而对称的AES可以简单理解基于一个密码的加解密,我只要有这个密码就可以加解密,并且速度非常快
4.所以APP在传输数据的时候生成一个十六位的密码,使用这个密码和AES对传输的数据进行加密,由于加密后是二进制,所以需要将加密后的值base64 encode一下,然后将该值作为body提交,密码使用公钥进行加密,一样base64后放在Header里,然后进行请求
5.网关发现请求包含加密数据,将请求转发到授权服务进行脱敏
6.授权服务从Header里获取密码,base64 decode后,使用该APP对应RSA对应的密钥进行解密,获取AES密码明文,然后使用密码对Body的数据进行解密,解密后将明文返回给网关
7.网关将对应的Body使用明文进行替换,打到下游业务服务,下游业务服务进行业务处理
9.业务服务进行业务处理后,将响应返回
10.网关将响应和明文密码转发给授权服务,授权服务直接用明文密码对响应进行AES加密,然后返回
11.APP拿到响应,使用刚才的AES密码对响应进行解密,然后进行页面渲染
12.整体流程完毕

这个流程可以防止在客户端进行抓包,因为传输到落地在协议层面数据都是加密的,只有在客户端内存里才会进行解密渲染。

但缺点也十分明显,完全依赖同步阻塞的串行模型,现代的网关比如Spring Gateway支持WebFlux 异步,导致请求响应授权服务、下游业务服务的线程不一样。比如网关将请求打到下游业务服务,线程就切换处理其他请求去了,这时业务服务的响应可能被另外的网关线程处理,而解密的明文密码还在上一个线程里,如何在交给授权服务进行加密?所以针对这种情况要额外设计对请求/响应的打点标记,额外增加复杂度