概述
在上一节中介绍了两种加密方法
- 对称加密
- 非对称加密
其中对称加密性能高,但是有泄露密钥的风险,而非对称加密相反,加密性能较差,但是密钥不易泄露,那么能不能把他们进行一下结合呢?
HTTPS采用混合加密
HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包,而SSL/TLS的加密方式就是采用了对称加密与非对称加密的结合。
SSL/TLS考虑到非对称加密的性能较低,所以在初始协商对称加密密钥时,使用了非对称加密,当对称加密密钥协商完成后,则后续所有的通讯,全部采用对称加密进行通讯。
但是这种方式无法证明公开密钥就是真实服务器的公开密钥,假设与B服务器进行通信,怎么确认公开密钥是B服务器的,后续在公开密钥传输途中已经被替换了,但是却发现不了。
由于任何人都可以访问服务器,所以不可能一一把公钥告诉他们,那么能不能提供一个公钥下载的地方让客户机访问服务器时先下载公钥,但是下载公钥的地址也有可能是假的,不可取。
那么有没有更好的方式,既能安全的获取公钥又能确保访问的服务器是真实的?答案:由数字证书认证机构颁发(CA)公开密钥证书
数字证书认证机构是客户端和服务器端都可以信赖的第三方机构,VeriSign就是一家数字证书机构。流程如下:
- 企业向证书机构提出公开密钥申请。
- 证书机构首先对公司身份进行核实,核实通过去,使用自己的私钥对企业服务器的公开密钥进行数字签名,并把签名信息绑定在公钥证书里下发给企业。
- 拿到证书的客户端对证书的签名进行校验,验证通过,即可确认:
- 服务器的公开密钥是值得信赖的
- 根据数字证书签发机构是真实有效的数字证书认证机构。
这里应该有人好奇,证书签发机构的公钥是怎么传到客户端的?浏览器在发布时,已经包含了主流的认证的机构的公开密钥了,所以是不需要传输的。
HTTPS通信流程
上图大致描述了 SSL/TLS 的握手过程,具体细节如下:
-
Client Hello
握手第一步是客户端向服务端发送 Client Hello 消息,这个消息里包含了一个客户端生成的随机数 Random1、客户端支持的加密套件(Support Ciphers)和 SSL Version 等信息。通过 Wireshark 抓包,我们可以看到如下信息:
-
Server Hello
第二步是服务端向客户端发送 Server Hello 消息,这个消息会从 Client Hello 传过来的 Support Ciphers 里确定一份加密套件,这个套件决定了后续加密和生成摘要时具体使用哪些算法,另外还会生成一份随机数 Random2。注意,至此客户端和服务端都拥有了两个随机数(Random1+ Random2),这两个随机数会在后续生成对称秘钥时用到。
-
Certificate
这一步是服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。
-
Server Hello Done
Server Hello Done 通知客户端 Server Hello 过程结束。
-
Client Key Exchange
客户端收到服务端传来的证书后,先从 CA 验证该证书的合法性,验证通过后取出证书中的服务端公钥,再生成一个随机数 Random3,再用服务端公钥非对称加密 Random3生成 PreMaster Key。
Client Key Exchange 就是将这个 key 传给服务端,服务端再用自己的私钥解出这个 PreMaster Key 得到客户端生成的 Random3。至此,客户端和服务端都拥有 Random1 + Random2 + Random3,两边再根据同样的算法就可以生成一份秘钥,握手结束后的应用层数据都是使用这个秘钥进行对称加密。为什么要使用三个随机数呢?这是因为 SSL/TLS 握手过程的数据都是明文传输的,并且多个随机数种子来生成秘钥不容易被暴力破解出来。客户端将 PreMaster Key 传给服务端的过程如下图所示:
-
Change Cipher Spec(Client)
这一步是客户端通知服务端后面再发送的消息都会使用前面协商出来的秘钥加密了,是一条事件消息。
-
Encrypted Handshake Message(Client)
这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。
-
Change Cipher Spec(Server)
这一步是服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。
-
Encrypted Handshake Message(Server)
这一步对应的是 Server Finish 消息,服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。
-
Application Data
应用层协议通信即发送HTTP请求。