HTTPS 相比于普通的加密传输,最根本的区别就是用于加密传输内容的秘钥是随机的。但 HTTPS 是怎么做到的呢? 总不能把秘钥直接发送给对方吧,因为只要发送,就可能被中间路由器截获。秘钥如果被截获,整个加密算法也就没有意义了。
HTTPS 使用了更聪明的做法,引入了一个叫做数字证书的机制。简单来说,每个支持 HTTPS 的服务端,都会申请一个 SSL 证书。这个证书一般是从专业的证书颁发机构申请。
我们平时访问 HTTPS 网站的时候,浏览器地址栏一般会出现一个小锁头,点击这个小锁头就可以查看证书信息, 我们来看google 的证书:
它的证书颁发机构是GeoTrust。 为什么一定要从这些颁发机构申请证书呢? 原因是 HTTPS 的证书链校验机制。比如我们请求google 的网站,它会先把证书信息发给我们的客户端。 然后我们客户端会做一个叫做证书链校验的操作。
所谓证书链校验,其实就是这样,每个证书都包含一个数字签名,用这个数字签名经过一系列算法,就可以匹配到上一级证书的签名,按照这个算法一直往上延伸,就可以匹配到最顶层证书的签名。就像上面google 那个证书的截图一样,证书是一级一级的树形结构。
匹配到最顶层证书有什么用呢? 答案是我们的客户端会预置这些顶层证书,比如打开你的mac 电脑的钥匙串程序,你会看到这样的内容:
我们平时使用的设备都会预置这些证书颁发机构的根证书。还回到前面讨论的证书校验的讨论,当逐级网上找到根证书后,就会和我们预置的这些证书进行匹配,如果能找到相同的,就代表网站发给我们的证书是可信的。否则这个网站就不可信。
这就解释了为什么我们需要从证书颁发机构申请证书了,因为只有证书颁发机构才可以生成它们根证书下面的子证书,生成子证书需要私钥,只有证书颁发机构才有自己的私钥。
说了这么多证书,到底数字证书有什么用呢? 它的作用其中一个是标识网站的身份,这个我们稍后会再详细介绍。
交换秘钥
如果证书验证通过了,就会开始一个交换秘钥的过程。 服务端发给客户端的证书,除了包含上述的验证信息,还包含了证书的公钥。 客户端验证证书有效后,就会发送给服务端一条消息,表明当前客户端可以接受的加密算法等信息,这条信息使用证书给我们的公钥加密传输。
服务端接收到这条消息后,因为它拥有证书的私钥,所以它可以用私钥将信息解密出来。因为私钥不会传输,所以只要不发生其他方式的泄露,理论上只有服务端才可能对这条消息解密。 保证了这条消息的安全性。
服务端知道客户端可以接受哪些加密算法后,就会生成一个针对这些算法的对称秘钥,是的,对称秘钥。然后再用自己的私钥把对称秘钥加密后返回给客户端。
同样,客户端得到这条消息,还会用之前收到的证书公钥再解密,得到这个对称秘钥。 到此为止 HTTPS 的握手过程就完成了。
接下来,客户端就可以用这个对称秘钥给服务端发送消息了。