小明(客户端)暗恋小红(服务端),想给小红写信,但是又怕信在邮递的过程中被人偷看,所以他把信装在一个盒子里锁起来,信虽然是安全了,但是小红就算收到了打不开啊,把钥匙给小红寄过去?万一钥匙也被人偷去了怎么办?
就在这时,小红想到了一个办法:小红把一个没有上锁的盒子寄给小明(钥匙在小红这),小明把钥匙放进去再锁上(小明可以锁盒子,但是一旦锁上了就连自己都打不开了),然后把这个装有钥匙的盒子寄回给小红,因为小红有钥匙,所以能打开盒子拿到里面的锁信件盒子的钥匙,再然后就能看到小明给她写的信了。同时,小红想回信的话,也可以把信装在这个盒子里寄回去,因为这是小明的盒子,他自己肯定还有一把锁,所以他也能打开,从此,小明和小红就可以任意的写信私通而不用担心其他人能看到了!
但是,如何保证小红寄送过来的未上锁盒子不被别人调包呢?这个等到我们介绍完HTTPS原理之后我们再回过头来看这个问题。
2.1.5.2. 单向认证下面这张图是网上比较常见的一张图:
这个应该算是精简版,省略了一些细节,但是对于理解https的核心原理部分足够了。下面这张图可能更全面(图片来源于这里,感谢作者)
具体过程如下:
浏览器访问一个https地址,同时向服务端发送支持的SSL协议版本、支持的加密算法、一个客户端生成的随机数(用于稍后生成"对话密钥")等。
服务端给客户端返回要使用的SSL协议版本号、加密算法、一个服务器生成的随机数(也同样用于稍后生成"对话密钥"),另外还有一个最重要的,返回服务器端的证书,即公钥证书;
客户端收到服务器回应以后,首先验证证书是否合法,如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期、或者返回的公钥不能正确解开返回证书中的数字签名,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从证书中取出服务器的公钥继续;
客户端向服务端发送自己所能支持的对称加密方案(注意是对称加密),供服务器端进行选择;
服务器端在客户端提供的加密方案中选择加密程度最高的加密方式;
服务器将选择好的加密方案通过明文方式返回给客户端;
客户端接收到服务端返回的加密方式后,使用该加密方式生成产生一个随机密钥(后续用作通信过程中对称加密的密钥),然后将该随机数用用证书中的公钥加密发给服务端;
服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获得最终的对称加密密钥。至此,客户端和服务端都得到一个随机密钥,并且这个密钥别人没法知道;
在接下来的会话中,服务器和客户端将会使用该密码进行对称加密解密,保证通信过程中信息的安全。
至于为什么会有三个随机数来生成最终的对称加密密钥,主要是为了进一步增大密钥的随机性,这里有一段不错的解释:
不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。
需要特别注意的是,以上握手阶段全部用的是HTTP协议明文传输的。
2.1.5.3. 回到小明和小红的故事