尽管如今HTTPS已经成了业界标配,前后端之间更常使用api进行数据传输,但穷逼中小型项目中,怎么保证数据在HTTP传输下保证安全?虽然本文所讲的安全通信实践并不完善,但也好过裸奔,有兴趣的话就来看看吧~
可用场景:n个客户端对某些固定服务端的HTTP安全通信
下面实现方案都有以下前提:
- 已知
公私钥对P
是 服务端或站点 提供的,而不是黑客假冒(可为线下约定,公钥P1
不担心泄漏,但私钥P2
绝不能泄漏) - 客户端中已经保存
公钥P1
,减少请求连接次数
一、如何保证安全登录
在聊怎么保证安全前,需要先知道:什么情境下不安全?下面先来看看大佬总结的“黑客定理”
黑客定理:
- 网络上传递的数据是不安全的,网络属于黑客公共场所,能被截取。
- 客户端是不安全的,属于黑客本地范畴,能被逆向工程。
- 用户客户端内存是安全的,属于黑客远端范畴,认为是安全的。
通过对这些定理的分析,可以得出:
- 网络上传递的数据,要先加密,再传输
- 任何客户端与服务端提前约定好的算法与密钥都是不安全的,不能固定密钥
- 密钥不能在网络上直接传输
那么,只要做到以上几点,数据在网络上的传输就有了一定的安全性
(ps:要是遇到黑客大佬,当我没说)
以登录为例进行安全的数据传输,示例时序图如下:
Q:为什么要随机生成公私钥对T
?像事先约定公私钥对P
一样,让服务端事先保存公钥T1
,客户端事先保存私钥T2
,不行吗?
A:如果客户端事先保存私钥T2
,那么通过反编译,黑客就能够从客户端中拿到私钥T2
,服务端通过公钥T1
加密的数据,就能够被黑客解密,不再安全;即使黑客拥有公钥P1
,也可以自己生成公私钥对T(伪)
,但是没有正确账密的他,并不能得到服务端的响应,无处着手。
登录是否搞复杂了?如果客户端不生成公私钥对T,直接生成对称密钥M,是否可行?
是可以的,这么做也能减少服务器生成对称密钥的步骤,提高服务器响应速度和处理效率。话不多说,直接看下图:
其实不管是生成公私钥对,还是生成对称密钥,或者使用其他密钥交换算法,都是借助“公钥加密的数据,仅拥有私钥的服务端能够解密阅读”这一特点,从而保证了密钥交换时的安全性。
二、如何防止重放攻击
Q:假设重新登录,token就重新生成,而黑客截取到了客户端发起的"使用公钥P1
加密(账号+密码+公钥T1
)"请求,即便他无法解析数据,但只要重新请求服务端,就导致已登录的用户可能出现登录过期/异常的情况,怎么处理?
A:需要对黑客的重放攻击进行防范,绝不能让其影响到实际业务,可以采用下面这种做法:
- 在真正登录之前,先进行一次"预登录"(携带一个自己要进行的登录标识,比如IP、用户名等进行请求),获取服务端颁发的"一次性准许登录凭证
voucher
" - 获取用户输入的账密,并携带voucher,请求服务端
- 服务端接收到voucher,需要对其进行检验:如果voucher可用,则进入正常流程,并销毁该voucher,防止该voucher再次使用产生数据重放问题;如果voucher已经被销毁,那便是数据重放,直接终止流程
再将上述的安全登录流程加上,整合后的时序图如下:
三、不登录,如何建立安全连接
上面是基于特定场景——登录才实现之后的安全通信,那能不能做到:不登录,一样能够安全通信呢?当然是可以的
还是那个前提:已知公私钥对P
是 服务端或站点 提供的,而不是黑客假冒(可为线下约定,公钥P1
不担心泄漏,但私钥P2
绝不能泄漏)
上面直接由客户端直接生成对称秘钥,是一种最为简单的算法,实际应用上,秘钥的交换算法多种多样,如ECDHE 秘钥交换算法(目前大部分网站的做法)、DHE 算法等。
只要能够借助“公钥加密的数据,仅拥有私钥的服务端能够解密阅读”这一特点,并保证客户端是随机生成密钥/公私钥对(防止反编译),那么就能够有无数种花样玩法了