Coding 应当是一生的事业,而不仅仅是 30 岁的青春。网上很多文章对 HTTPS 的讲解云里雾里,看完这篇,如果还不理解,骂我渣男好了!
图片来自 Pexels
整个 HTTPS 的演变跟流程细思极恐,有很多思想可以借鉴学习。我以后要离搞安全的朋友远一点。
这篇将带你深入 HTTPS 加解密原理,希望看完能够有这些收获:
明白 HTTPS 到底解决了什么问题
理解对称加密与非对称加密的原理和使用场景
明白 CA 机构和根证书到底起了什么作用
Why HTTPS
近几年来,各大公司都在大力推进 HTTPS 的建设:
Google Chrome 将非 HTTPS 的网站标注为不安全。
苹果要求 APP 中需要使用 HTTPS 进行通信。
微信小程序也要求使用 HTTPS 协议。
那么,我们为什么非要做这么一件事呢?我们先来看看 HTTP。
HTTP(Hypertext Transfer Protocol)超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议,可以说 HTTP 是当代互联网通信的基础。
这一攻击手法叫做 MITM(Man In The Middle)中间人攻击。
举个例子,稍微有点长,但这个例子透露出了怪怪我对安全如此痴迷的原因。
甚至有时候本来要下载一个文件,最后下下来却变成了另外一个完全不同的东西,这些都是被运营商劫持了 HTTP 明文数据的现象。
运营商劫持
HTTPS 实现原理
工作流程
我们先来看看 HTTPS 的加解密流程,如下图:
HTTPS 加解密流程如下:
用户在浏览器发起 HTTPS 请求(如 https://www.mogu.com/),默认使用服务端的 443 端口进行连接。
HTTPS 需要使用一套 CA 数字证书,证书内会附带一个公钥 Pub,而与之对应的私钥 Private 保留在服务端不公开。
服务端收到请求,返回配置好的包含公钥 Pub 的证书给客户端。
客户端收到证书,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效(递归判断,直到判断到系统内置或浏览器配置好的根证书),如果不通过,则显示 HTTPS 警告信息,如果通过则继续。
客户端生成一个用于对称加密的随机 Key,并用证书内的公钥 Pub 进行加密,发送给服务端。
服务端收到随机 Key 的密文,使用与公钥 Pub 配对的私钥 Private 进行解密,得到客户端真正想发送的随机 Key。
服务端使用客户端发送过来的随机 Key 对要传输的 HTTP 数据进行对称加密,将密文返回客户端。
客户端使用随机 Key 对称解密密文,得到 HTTP 数据明文。
- 后续 HTTPS 请求使用之前交换好的随机 Key 进行对称加解密。
对称加密与非对称加密
又是对称加密又是非对称加密,一会公钥一会私钥一会随机 Key,为什么要这么复杂呢,一套搞到底不好么?
对称加密是指有一个密钥,用它可以对一段明文加密,加密之后也只能用这个密钥来解密得到明文。
如果通信双方都持有密钥,且天知地知你知我知,绝对不会有别的人知道,那么通信安全自然是可以得到保证的(在密钥足够强的情况下)。
然而,在 HTTPS 的传输场景下,服务端事先并不知道客户端是谁,你也不可能在事先不通过互联网和每一个网站的管理员都悄悄商量好一个通信密钥出来。
但这个公钥之前就在互联网上传输过,很有可能已经有人拿到,并不安全,所以这一过程只用非对称加密是不能满足的。
注意,严格来讲,私钥并不能用来加密,只能用作签名使用,这是由于密码学中生成公钥私钥时对不同变量的数学要求是不同的。
服务端有非对称加密的公钥 A1,私钥 A2。
客户端有非对称加密的公钥 B1,私钥 B2。
客户端向服务端发起请求,服务端将公钥 A1 返回给客户端。
浏览器收到公钥 A1,将自己保存的公钥 B1 发送给服务端。
之后浏览器所有向客户端发送的数据,使用公钥 B1 加密,客户端可以使用私钥 B2 解密。
客户端所有向服务端发送的数据,使用公钥 A1 加密,服务端可以使用私钥 A2 解密。
此时,两条传输方向的数据都经过非对称加密,都能保证安全性,那么为什么不采用这种方案呢?
最主要的原因是非对称加解密耗时要远大于对称加解密,对性能有很大损耗,大家的使用体验很差。
所以,我们才最终选用了上文介绍到非对称加密+对称加密的方案,再复习一下:
服务端有非对称加密的公钥 A1,私钥 A2。
客户端发起请求,服务端将公钥 A1 返回给客户端。
客户端随机生成一个对称加密的密钥 K,用公钥 A1 加密后发送给服务端。
服务端收到密文后用自己的私钥 A2 解密,得到对称密钥 K,此时完成了安全的对称密钥交换,解决了对称加密时密钥传输被人窃取的问题。
之后双方通信都使用密钥 K 进行对称加解密。
CA 颁发机构
中间人利用自己的私钥 B2 解密,得到密钥 K,再使用服务端的公钥 A1 加密传送给服务端,完成了通信链路,而服务端和客户端毫无感知。
HTTPS 中间人
CA 机构拥有自己的一对公钥和私钥。
CA 机构在颁发证书时对证书明文信息进行哈希。
将哈希值用私钥进行加签,得到数字签名。
明文数据和数字签名组成证书,传递给客户端:
客户端得到证书,分解成明文部分 Text 和数字签名 Sig1。
用 CA 机构的公钥进行解签,得到 Sig2(由于 CA 机构是一种公信身份,因此在系统或浏览器中会内置 CA 机构的证书和公钥信息)。
用证书里声明的哈希算法对明文 Text 部分进行哈希得到 H。
- 当自己计算得到的哈希值 T 与解签后的 Sig2 相等,表示证书可信,没有被篡改。
这时,签名是由 CA 机构的私钥生成的,中间人篡改信息后无法拿到 CA 机构的私钥,保证了证书可信。
注意,这里有一个比较难以理解的地方,非对称加密的签名过程是,私钥将一段消息进行加签,然后将签名部分和消息本身一起发送给对方。
收到消息后对签名部分利用公钥验签,如果验签出来的内容和消息本身一致,表明消息没有被篡改。
在这个过程中,系统或浏览器中内置的 CA 机构的证书和公钥成为了至关重要的环节,这也是 CA 机构公信身份的证明,如果系统或浏览器中没有这个 CA 机构,那么客户端可以不接受服务端传回的证书,显示 HTTPS 警告。
有些老旧的网站会要求使用前下载安装他自己的根证书,这就是这个网站使用的证书并不能在系统内置的 CA 机构和根证书之间形成一条信任链,需要自己安装根证书来构成信任链,这里的风险就要使用者自己承担了。
证书明细
总结
为了兼顾性能和安全性,使用了非对称加密+对称加密的方案。
为了保证公钥传输中不被篡改,又使用了非对称加密的数字签名功能,借助 CA 机构和系统根证书的机制保证了 HTTPS 证书的公信力。