前言
关于HTTPS的文章有很多,大家的文章讲的那是真的详细,功底我着实佩服。虽然已经有了这样优秀的文章,但不影响我写作的热情,学习知识,分享是必不可少的一环。文章不是照搬,而是自己理解加工后纯手打的。
学习前端开发果然还是绕不开计算机网络基础,今天面试挂在了这里,痛定思痛,让我们一起来了解下HTTPS到底是个什么玩意。
灵魂拷问
你是否曾认为,证书是用来加密的?😄
对称加密
通信双方,使用同一个密钥对信息加密和解密。只有知道密钥的人才能获取内容。
但通信双方必须约定好密钥,且不能泄露密钥。而实际上,只要使用网络传输,就存在报文泄露的风险。何况HTTP协议本就是明文传输,双方约定密钥的过程,完全是众目睽睽之下。这种情况下无法保证你的密钥没有被第三方截获。隔墙有耳一说,对吧?所以出现了非堆成加密
非对称加密
通信双方每个人都有两把钥匙,公钥任何人都可以知道,私钥只有自己知道。
且存在这样一个特点:使用公钥加密的内容,只有对应的私钥才能解开,使用私钥加密的内容,只有对应的公钥才可以解开。所谓,非对称。
根据这样的特点,A发消息给B,使用B的公钥加密,B收到后使用自己的私钥解密,就可以获取到内容了。
所以通信时,双方首先要互换公钥。A和B通信开始后,中间人完全可以在截获A的公钥后,替换成自己的公钥发送给B,只要B使用该公钥加密,中间人就可以使用自己的私钥解密,获得内容。双方的通信虽不至于众目睽睽,却也暴露给了中间人,总归是不安全的。
你可能要问了,那B不用中间人的公钥加密不就好了?
实际上B并不知道该公钥是不是A的,A也同样不确定它收到的公钥是不是来自B。
所以引出了一个问题。A如何判断你加密使用的公钥确实是B的,而不是中间人的?即,如何判断公钥身份是否有效?
数字证书:
联系实际,考虑到身份证明必须要第三方机构,我们必须无条件信任它。自己是没办法证明自己的身份的。这个第三方机构一般是CA(Certificate Authority),颁发证书的具体过程如下:
B将自己的个人信息,和公钥发送给CA机构(这里会不会出现中间人攻击?),CA机构使用哈希算法对发来的个人信息和公钥进行计算,生成一个摘要,并使用CA自己的私钥进行加密生成数字签名。最后将数字签名和原信息(B的公钥和信息)合并,生成数字证书。
这里用到了哈希算法,它的特点是,只要原信息变化,计算得到的值就会发生巨大的变化。以此来确认内容是否遭到篡改
再借鉴一张图:

所以,在通信时,B先将自己的证书发送给A,A使用同样的哈希算法,对证书内B的信息进行计算,生成一份摘要。同时对证书内的数字签名进行解密,拿到事先加密的摘要,对比两份摘要的内容是否一致,便可以确定公钥是否被篡改。
最根本的问题
- 公钥发送给CA机构的过程中,不会被中间人拦截吗?
- 数字签名是使用CA的私钥加密的,解密需要使用CA的公钥,我们如何获取?获取公钥的过程中如果又被截获了,岂不成了死循环?
根证书
以下内容摘自百度百科
根证书是CA认证中心给自己颁发的证书,是信任链的起始点。安装根证书意味着对这个CA认证中心的信任。从技术上讲,证书其实包含三部分,用户的信息,用户的公钥,还有CA中心对该证书里面的信息的签名。验证一份证书的真伪(即验证CA中心对该证书信息的签名是否有效),需要用CA 中心的公钥验证,而CA中心的公钥存在于对这份证书进行签名的证书内,故需要下载该证书,但使用该证书验证又需先验证该证书本身的真伪,故又要用签发该证书的证书来验证,这样一来就构成一条证书链的关系,这条证书链在哪里终结呢?答案就是根证书,根证书是一份特殊的证书,它的签发者是它本身,下载根证书就表明您对该根证书以下所签发的证书都表示信任,而技术上则是建立起一个验证证书信息的链条,证书的验证追溯至根证书即为结束。所以说用户在使用自己的数字证书之前必须先下载根证书。
一般来说,根证书是内置在操作系统/浏览器中的,随操作系统的发布而发布。你信任操作系统,也就信任了这份证书。这就是证书链条的终点。
HTTPS
终于到了HTTPS。前面我们提到了加密算法和证书。HTTPS是如何选择的?
首先,安全起见,我们应该使用非对称加密算法。但实际上这种算法的效率并不够高,可以想象,存在两次加密解密的过程。而对称加密算法的效率就还算不错。于是产生了这样一种思路:
使用对称加密算法来传输信息,但密钥使用非对称加密算法来传输。所以希望大家牢记:HTTPS中,非对称加密算法,仅用来传递对称加密算法的密钥。
握手过程
HTTPS握手过程分为四个阶段:
- 浏览器发起HTTPS请求,生一次个随机数,附带上支持的加密算法列表和协议版本号。
- 服务器验证协议版本号是否一致,一致则生成一个随机数,随证书一同发送回客户端,否则拒绝请求。
- 浏览器通过根证书验证服务器证书是否有效,若有效则说明证书中的服务器公钥有效。生成一个随机数,再生成一个所有内容的哈希值(一共三个随机数),并使用服务器公钥加密后发送。若证书无效,则浏览器提示风险。
- 服务器接收到之后,使用私钥解密发来的内容,并对所有内容进行同样的哈希值计算,再和收到的哈希值比对。若内容一致,则通过三个随机数按照约定的加密算法生成会话密钥(也就是对称加密密钥),并回应客户端握手完成。
注意到,前两次握手过程是明文传输的。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用会话密钥来加密内容
为什么需要三个随机数?这三个随机数又被称为pre-master key
引用d520的解释:
不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。 对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。 pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。
断开连接后如何恢复:
- session ID:每一次会话都有一个编号,会话中断后再次连接需要客户端给出这个编号。服务器有这个记录则不用重新连接。此种方式对分布式集群不太友好
- session ticket:只有服务器能解密,里面包含会话信息。是在上一次会话中发给用户的。