我正在参加「掘金·启航计划」
HTTPS 是什么
Hypertext Transfer Protocol Secure (HTTPS) is an extension of the Hypertext Transfer Protocol (HTTP). It uses encryption for secure communication over a computer network, and is widely used on the Internet.[1][2] In HTTPS, the communication protocol is encrypted using Transport Layer Security (TLS) or, formerly, Secure Sockets Layer (SSL). The protocol is therefore also referred to as HTTP over TLS,[3] or HTTP over SSL.
以上是 HTTPS
在维基百科的定义,简单概括就是:“HTTPS
是对 HTTP
的扩展,其使用加密技术在计算机网络上进行安全通信,并在互联网上有广泛的应用。在 HTTPS
中,通信协议使用的是 TLS
或早期的 SSL
。所以 HTTPS
也被称为 TLS
或 SSL
之上的 HTTP
”。
“TLS
或 SSL
之上的 HTTP
”,是否说明了 HTTP
与 "S"
是独立分开的?确实是的,HTTPS
中 HTTP
负责传输,"S"
负责安全。而这个 "S"
新版本叫 TLS
,老版本叫 SSL
。
SSL/TLS 简单发展历程
SSL(Secure Sockets Layer) 是网景公司(Netscape)设计的主要用于Web的安全传输协议,这种协议在Web上获得了广泛的应用。 基础算法由作为网景公司的首席科学家塔希尔·盖莫尔(Taher Elgamal)编写,所以他被人称为“SSL之父”。
- 1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
- 1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
- 1996年,SSL 3.0版问世,得到大规模应用
- 1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版 TLS (Transport Layer Security) 1.0版。
- 2006年4月,IETF发布TLS 1.1版本(RFC4346),包含一些小的安全改进。2008年8月,TLS 1.2版本(RFC5246)发布,移除了老旧加密套件,增强了协议的安全性,TLS 1.2协议是目前主流的TLS协议版本。
- 2018年3月,TLS 1.3协议正式批准问世,成为了新一代TLS协议版本。TLS 1.3版本历经长达4年28次草案修改,是迄今为止改动最大的一次,既能提高互联网用户的访问速度,又能增强安全性,大大提升HTTPS连接的速度性能,用户的使用体验度得到明显的提升。
所以HTTPS
本质上就是HTTP
+TLS
,其安全通信是靠 TLS
(指 SSL/TLS)来完成的。它们的工作流程简单来说是:利用非对称加密协商一个对称加密密钥,再用这个密钥在每次通信时加解密。 关键词加密、解密,那我们就先来看看HTTPS
用到了哪些加密技术。什么是对称、非对称加密?Hash是加密么?,如果不了解加密的,一定要看,理解加密对于理解 HTTPS 握手过程非常重要,如果已经了解可以跳过。
在了解加密、Hash 之后我们来看看 HTTPS 是如何用这些技术手段工作的。
HTTPS 握手
这是一个最常规的握手流程,不需要验证客户端身份但需要验证服务端身份,也叫单向认证。
上图是Wire Shark
工具抓包的握手信息,下面我们来通过这张图详细聊聊这个握手的过程,把步骤一步步拆解。
Client Hello
Client Hello
是 TLS 握手的第一个步骤,不是指客户端向服务端发送了一个Client Hello
字符串,而是这个步骤的名称叫作Client Hello
,包括后面的 Server Hello
等等都是步骤的名称。Client Hello
表示客户端向服务端发起了一个TLS
握手请求,那我们来看看这个请求发送了哪些信息。
可以看到 Client Hello 后面有个 1
,这其实就是客户端发给服务端的实际值。服务端收到这个1
就知道客户端发起了TLS
链接请求。此外除了Client Hello
,本次报文内容主要还包括以下信息:
- 支持的
TLS
版本 把客户端支持的最佳TLS
版本告知服务端,服务端选择一个支持的版本 - 支持的加密套件类型(Cipher suite) 客户端支持的加密套件列表,按优先级顺序排列(对称、非对称加密、Hash,不了解这些可以先阅读什么是对称、非对称加密?Hash是加密么?,不了解的同学一定要看,非常重要!!!)
- 客户端随机数 ,每次握手的随机数都不一样,这个随机数也会在客户端保存,用来生成密钥
这些就是Client Hello
的主要内容,主要向客户端发送其支持的工具种类和随机数。
Server Hello
服务端在收到Client Hello
之后,发送的内容结构跟Client Hello
对应,会向客户端发送选择的TLS版本
、加密套件类型
,同时还有客户端随机数
。现在,客户端与服务端就都有了基础共同信息。
Certificate
这一步还是服务端向客户端发消息,Certificate(不了解证书的同学,可以看这篇文章HTTPS 用到的数字证书是怎么一回事? - 掘金 (juejin.cn)) 消息用于携带服务器 X.509 证书链,目的是让客户端校验服务端身份。
Server Key Exchange
ServerKeyExchange 是可选的,消息内容对于不同的协商算法套件会存在差异。部分场景下,比如使用 RSA 算法时,服务器不需要发送此消息。
此处基于 DH 算法的握手,需要单独发送一条 ServerKeyExchange 消息带上Server Params
,这是 DH 算法所需参数,用于协商密钥
Server Hello Done
这一步是服务端向客户端发送一个单字节数据,表示已将所有预计的握手信息发送完毕,后面将等待客户端发送消息。
Verify Certificate
客户端验证服务端发来的证书信息,验证通过才会继续通信,否则中断或提示,具体验证信息如下:
- 证书链的可信性
- 证书是否被吊销
- 证书有效期
- 证书主机名是否与请求主机名一致 验证大致过程:先读取证书明文信息,根据对应散列函数获取摘要信息;利用公钥解密相关签名信息得到摘要,对比两个摘要,如果信息一致则整数合法;再去查询证书其他信息
Client Key Exchange
证书验证通过之后,客户端会生成预主密钥pre-master
,不过会因不同的密钥协商算法而有差异:
- 如果是
ECDHE
算法,会根据服务端 ECDHE 参数
、服务端 ECDHE 参数
计算出一个主密钥pre-master
- 如果是
RSA
算法,则用随机算法生成pre-master
,
怎么把这个pre-master
给服务端也会因协商密钥的算法而有差异。
此处使用的是 ECDHE
算法,ClientKeyExchange
传递的是算法的客户端参数
,如果使用的是 RSA 算法则此处应该传递用公钥对pre-master
加密后的密文。
此时客户端有client-random
、server-random
、pre-master
三个随机数,然后会根据这三个参数生成master-secret
,再根据master-secret
生成了
- client encryption key
- server encryption key
- client MAC key
- server MAC key
encryption key
是对称加密密钥,服务端客户端用各自的密钥加解密;MAC
是 Message Authenticate Code (TLS 使用 HMAC)的缩写,它是一个数字签名,用来验证数据的完整性,可以检测到数据是否被篡改。
Change Cipher Spec、
通知服务端后续的消息都采用协商的通信密钥和加密算法进行加密通信,发送一个单字节数据
Finished
这一步客户端会将前面握手步骤的信息结合到一起,再用client MAC key
生成MAC
,再用刚刚产生的client encyption key
加密,,发送到服务端。
Server Verify
根据握手算法,如果是RSA
算法就用私钥解密获取到pre-master
;如果是DH
算法就结合DH Client Params
计算出 pre-master
。然后跟客户端一样,得到master-secret
生成了,再生成与客户端相同的四个密钥。
密钥生成之后,用client encryption key
和 MAC key
校验客户端发过来的 Encrypted HandShake Message
.
Change Cipher Spec、Finish.
这两步对应客户端的操作,是一样的,这边就不重复了。主要就是客户端验证服务端的加密后的握手消息。
握手结束
经过以上的步骤,握手过程就结束了,下面就可以用约定的密钥进行加密通信了。
应用数据在传输之前,首先要附加上MAC key
,然后再对这个数据包使用encryption key
进行加密。在服务端收到密文之后,使用client encryption key
进行解密,客户端收到服务端的数据之后使用server encryption key
进行解密,然后使用各自的MAC key
对数据的完整性包括是否被篡改进行验证。
一段话总结握手过程
TLS
客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello
来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,TLS
的服务器端会回应一个ServerHello
,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个pre-master
,用TLS
服务器的公钥加密后传过去(或「DH算法」计算出),TLS
服务器端用自己的私钥解密后(或「DH算法」计算出),会话密钥协商成功,双方可以用同一份会话密钥来通信了。