用 HTTP 协议,看个新闻还没有问题,但是换到更加严肃的场景中,就存在很多的安全风险。例如,你要下单做一次支付,如果还是使用普通的 HTTP 协议,那你很可能会被黑客盯上。例如在点外卖的环境中,发送的网络包可能会被黑客截获,获取到你的银行卡账号以及密码。
解决这个问题的思路是加密,分为两种,一种是对称加密(加密和解密用同一个密钥,效率会更高),一种是非对称加密(公钥加密,私钥解密)。
对称加密
在刚才的点外卖场景中,和外卖网站约定了一个密钥,你发送请求的时候用这个密钥进行加密,外卖网站用同样的密钥进行解密。这样就算中间的黑客截获了你的请求,但是它没有密钥,还是破解不了。但问题是怎么约定这个密钥呢?如果是在互联网上传输,那么还是有呗截获的风险,线下传输又不实际。所以这时候要非对称加密的接入。
非对称加密
非对称加密的私钥放在外卖网站这里,不会在互联网上传输,这样就能保证这个秘钥的私密性。但是,对应私钥的公钥,是可以在互联网上随意传播的,只要外卖网站把这个公钥给你,你们就可以愉快地互通了。
另外,这个过程还有一个问题,黑客也可以模拟发送“我要定外卖”这个过程的,因为它也有外卖网站的公钥。为了解决这个问题,看来一对公钥私钥是不够的,客户端也需要有自己的公钥和私钥,并且客户端要把自己的公钥,给外卖网站。
这样,客户端给外卖网站发送的时候,用外卖网站的公钥加密。而外卖网站给客户端发送消息的时候,使用客户端的公钥。
数字证书
不对称加密也会有同样的问题,如何将不对称加密的公钥给对方呢?一种是放在一个公网的地址上,让对方下载;另一种就是在建立连接的时候,传给对方。这两种方法有相同的问题,那就是,作为一个普通网民,你怎么鉴别别人给你的公钥是对的。会不会有人冒充外卖网站,发给你一个它的公钥。接下来,你和它所有的互通,看起来 都是没有任何问题的。毕竟每个人都可以创建自己的公钥和私钥。
这个时候就需要权威部门的介入了,就像每个人都可以打印自己的简历,说自己是谁,但是有公安局盖章的,就只有户口本,这个才能证明你是你。这个由权威部门颁发的称为证书 (Certificate)。
证书里面有公钥,还有证书的所有者,另外还有证书的发布机构以及证书的有效期,生成证书需要发起一个证书请求,然后将这个请求发给一个权威机构去认证,这个权威机构我们称为CA( Certificate Authority)。
将证书请求的命令发给权威机构,权威机构会通过签名算法给证书盖个章,问题是怎么知道签名是真的权威机构的签名呢?这里用的是CA的私钥。
签名算法大概是这样工作的:一般是对信息做一个 Hash 计算,得到一个 Hash 值,这个过程是不可逆的,也就是说无法通过 Hash 值得出原来的信息内容。在把信息发送出去时,把这个 Hash 值加密后,作为一个签名和信息一起发出去。CA 用自己的私钥给外卖网站的公钥签名,就相当于给外卖网站背书,形成了外卖网站的证书。这样子,你不会从外卖网站上得到一个公钥,而是会得到一个证书,这个证书有个发布机构 CA,你只要得到这个发布机构 CA 的公钥,去解密外卖网站证书的签名,如果解密成功 了,Hash 也对的上,就说明这个外卖网站的公钥没有啥问题。
HTTPS的工作模式
非对称加密在性能上不如对称加密,所以HTTPS就是将江浙结合起来,总体思路就是公钥私钥主要用于传输对称加密的秘钥,而真正的双方大数据量的通信都是通过对称加密进行的。
登录一个外卖网站的时候,由于是 HTTPS,客户端会发送 Client Hello 消息到服务器,以明文传输 TLS 版本信息、加密套件候选列表、压缩算法候选列表等信息。另外,还会有一个随机数,在协商对称密钥的时候使用。
然后,外卖网站返回 Server Hello 消息, 告诉客户端,服务器选择使用的协议版本、加密套件、压缩算法等,还有一个随机数,用于后续的密钥协商。
然后,外卖网站会给你一个服务器端的证书,然后说:“Server Hello Done,我这里就这些信息了。”
你当然不相信这个证书,于是你从自己信任的 CA 仓库中,拿 CA 的证书里面的公钥去解密外卖网站的证书。如果能够成功,则说明外卖网站是可信的。这个过程中,你可能会不断往上追溯 CA、CA 的 CA、CA 的 CA 的 CA,反正直到一个授信的 CA,就可以了。
证书验证完毕之后,觉得这个外卖网站可信,于是客户端计算产生随机数字 Pre-master, 发送 Client Key Exchange,用证书中的公钥加密,再发送给服务器,服务器可以通过私钥解密出来。
到目前为止,无论是客户端还是服务器,都有了三个随机数,分别是:自己的、对端的,以及刚生成的 Pre-Master 随机数。通过这三个随机数,可以在客户端和服务器产生相同的对称密钥。
有了对称密钥,客户端就可以说:“Change Cipher Spec,咱们以后都采用协商的通信密钥和加密算法进行加密通信了。”
然后发送一个 Encrypted Handshake Message,将已经商定好的参数等,采用协商密钥进行加密,发送给服务器用于数据与握手验证。
同样,服务器也可以发送 Change Cipher Spec,说:“没问题,咱们以后都采用协商的通信密钥和加密算法进行加密通信了”,并且也发送 Encrypted Handshake Message 的消息试试。当双方握手结束之后,就可以通过对称密钥进行加密传输了。 这个过程除了加密解密之外,其他的过程和 HTTP 是一样的,过程也非常复杂。