HTTPS主要就是为了对通信数据进行加密,因此首先我们需要从加密的角度入手。不加密主要会面临以下三种风险:
- 被窃听:http是明文传输,随便一抓包就知道了
- 被篡改:恶意劫持修改请求内容
- 被冒充:劫持流量到假网站
为了应对这些问题,我们需要对请求内容加密。但是加密后的数据必须要能快速地解出来,不然加密就没意义了。所以像md5这种不可逆的加密算法肯定就不可行。一般来说有两类加密算法:
- 对称加密:加密方和接收方都用同一个密钥进行加密和解密
- 非对称加密:有一对(两个)密钥,A和B,用A加密则必须用B解密,用B加密则必须用A解密
对称加密不可行
如果在网络请求中使用对称加密,那在发送请求前,通信双方都必须约定好使用什么密钥。这基本不可行:
- 客户端无数个,服务端需要为每个客户端的每次连接分配一个密钥吗?太多了,无法维护
- 即使服务端维护N个密钥, 客户端怎么知道这个密钥是真的? 比如客户端发送请求到baidu.com,但是中途被恶意软件拦截,返回一个密钥。后续的通讯可全都是在和恶意软件通信,如果恶意软件做一个假百度,你根本看不出来
- 如果都用同一个密钥,那只要有任何一个客户端泄漏,那就都泄漏了(黑客甚至自己去正常请求一下就能拿到密钥,等于没加密)
所以对称加密的方案不可行
非对称加密
非对称加密一般是一个公钥一个私钥。服务端持有私钥,公钥所有人可见。客户端在和服务端3次握手之后,不是立刻开始发送数据,而是先去服务端获取公钥。之后利用公钥加密数据发送,服务端用私钥解密。服务端response也用私钥加密,客户端就可以用公钥解密。比如有公钥Pub和私钥Prv:
- 加密(data, Pub) -> encrypedData, 解密(encrypedData, Prv) -> data
- 加密(data, Prv) -> encrypedData, 解密(encrypedData, Pub) -> data
但是这里有两个问题:
- 非对称加密性能很差,再也不能愉快地上网冲浪了
- 通对称加密的问题一样,你怎么知道你拿到的是目标服务器的公钥?中途被劫持了怎么办?
解决性能
先只考虑解决性能问题。由于非对称加密性能着实堪忧,那么我们是不是可以让客户端和服务端在正式发送数据前,先用非对称加密约定出一个值,之后就用这个值作为密钥进行对称加密。https就是这个原理。
请求劫持的问题
但是这一切还是要建立在请求能够正确地发到目标服务端才行,如果中途被劫持了,和黑客进行非对称加密,最后和黑客进行对称加密,一切也是徒劳。那么问题的核心就变成了,如何可靠地获取服务端的公钥以及约定出一个共同的私钥。
TLS利用4次握手和CA解决这个问题。在3次握手建立好链接后,还要经历一个TLS4次握手:
- c -> s: TLS版本,随机数A, 支持的加密算法有这些…
- c <- s: 就用你的TLS版本,随机数B,用你支持的算法中的RSA,服务器的证书CA
- c -> s: 先验证CA,如果验证通过则发送:随机数C(用公钥加密),前面的通信内容加随机数C一起hash得到的hash值
- c <- s: 服务端再hash一下
第三次和第四次握手只是为了保证安全,我们先把注意力放到这里面的核心,也就是服务器证书CA。CA其实就是一系列信息,包含服务器的信息,以及服务器的公钥。但是问题是我怎么知道这个CA真的是那个服务器上的而不是中途被黑客劫持返回给我的假的?——公信机构
市面上有很多公信机构,服务器的维护者去公信机构上申请CA。客户端拿到服务端返回的CA后需要去公信机构验证这个CA是不是真的。但是问题又来了,如果黑客能够劫持你对服务器的请求,他也可以劫持你去公信机构验证CA的请求。如果是这样,那不是还是有问题吗?
确实是这样。为了能够验证服务端发回的CA的有效性,客户端需要先去公信机构验证CA。为了保证去往公信机构的请求不被劫持,操作系统内置了一些公信机构的公钥(私钥由那些公信机构保管)。因此,客户端只需要查看服务端返回的CA,找到签发的公信机构,再去操作系统中找到对应机构的公钥,利用此公钥对CA进行加密,再到公信机构去验证。因为使用了公钥进行非对称加密,因此黑客即使劫持了请求:
- 它没有私钥,无法解析你的请求内容
- 它如果想直接给你返回一个success,让你误以为成功,但是它没有私钥,没法加密(你会通过公钥解密)
因此CA非常重要,是SSL/TLS的核心。
客户端验证完CA之后,就可以确认对端确实是你想访问的服务端。这时客户端可以随机出一个密钥X用户后续对称加密,利用公钥加密后告诉服务端。后续的请求就能够利用对称加密进行了。
但是实际上TLS并不是由客户端随机生成一个对称加密密钥,因为考虑到如果随机算法写得有问题,可能是伪随机。如果是伪随机,且被黑客找到规律,那他就能够用较小的代价猜出你们的对称加密密钥。因此,TLS中采用了3个随机数,客户端第一次发送的A,服务端返回的B,已经第三次客户端发送的C。客户端和服务端都能得到这3个随机数,利用约定好的生成算法,就可以生成同样的后续用于对称加密的密钥而不需要通知对方。
就算伪随机又怎样,我客户端伪随机,服务端伪随机,客户端再伪随机,三个随机数叠加在一起,看你怎么猜!!
总结
以上就是https的核心原理,最关键的就是理解CA,以及如何保证去公信机构验证CA不会被黑客劫持或篡改。
由于https在真正发送数据前总共有7次握手,其中还涉及到一轮非对称加密,因此建立https连接的代价是很高的。后续尽量使用长连接,否则如果每次都进行7次握手,可以想象性能会非常差!
网友评论