我理解的 HTTPS

HTTPS 是 HTTP 的安全版,在 HTTP 下增加了 SSL 层,对传输的数据进行了加密,使得通信更加的安全。但是,因为 HTTPS 需要建立更多的通信,并且数据在传输的过程中需要进行加密、解密,所以网站访问速度要比 HTTP 慢。

以前我对于 HTTPS 的了解仅限于此,知其然不知其所以然。前段时间在工作中需要部署 HTTPS,趁着这次机会更加全面的了解了 HTTPS,现通过这篇博客谈谈我对于 HTTPS 的一点理解。

加密算法

HTTPS 协议下传输的数据都进行了加密,因此在了解 HTTPS 之前需要先了解一下加密算法。

加密算法有很多,主要可以分为对称加密算法非对称加密算法对称加密通过加密算法和密钥对原始数据进行加密得到密文,如果想要获得原始数据,则需要使用加密时使用的密钥及算法的逆算法对密文进行解密,在对称加密算法只使用一个密钥,如:DES 算法非对称机密与对称加密不同之处在于,非对称加密过程中需要使用两个密钥,这两个密钥被称为公钥和私钥,公钥加密后的数据只能使用私钥解密,而私钥加密后的数据只能使用公钥解密,较之对称加密具有更高的安全性,如:RSA 算法

除了对称加密和非对称加密之外,还有一类加密算法叫做 Hash 算法

哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。一般用于快速查找和加密算法。

Hash 算法 是不可逆算法,不可逆指无法(并不是完全没有办法,只是难度很高)根据密文得到原始数据。同时,即使原始数据发生一点变化,通过 Hash 算法得到的 Hash 值也将不同,因此 Hash 算法通常用来生成信息摘要或签名,如:MD5 算法

HTTPS 的原理

我们都知道 HTTP 协议是明文传递数据的,这就导致了在数据传递的过程中如果被第三方截获,那么通信内容对于第三方就是完全透明的。因此,如果要保证通信的安全,最先想到的就是对传输的数据进行加密,这样即使被第三方截获,他也无法得知通信的原始内容。

根据上文提到的加密算法,如果要加密数据,可以使用对称加密或者非对称加密。对称加密和非对称加密的区别在于,对称加密中加密和解密使用的是相同的密钥,而非对称加密中使用的是公钥和私钥,因此 非对称加密要比对称加密更加安全,不过在执行效率上,对称加密比非对称加密的效率要高得多,尤其是在数据较大时,如果使用非对称加密会很慢。因此,对于数据的加密,应该使用对称加密。但是,使用对称加密时却存在一个问题,那就是 通信双方无法安全的进行密钥交换,因为在密钥的传输过程中,有可能密钥会被第三方所截获,一旦密钥被截获,那么传输的密文就可以被第三方解密出来,丧失安全性。因此对称加密的密钥不能通过明文传输,必须也要经过加密

那么应该如何加密对称加密时使用的密钥呢?如果仍然使用对称加密,那么就进入到了一个死循环状态,此时,就轮到非对称加密登场了。非对称加密解决了对称加密中的密钥传输问题,它使用了两个密钥,其中公钥通常用来分发,而私钥则自己保留。在建立安全通信时,由通信的一方(以下称为“甲方”)生成公钥和私钥,然后将公钥传输给另一方(以下称为“乙方”),其中公钥采用明文传输的方式。乙方在收到甲方传递过来的公钥后,生成对称加密的密钥,然后用公钥进行加密并将加密后的密文返回给甲方。甲方在收到包含对称加密密钥的密文后,使用自己保留的私钥进行解密即可获得密钥。此后,双方就能使用对称加密的密钥进行安全的通信了。

在上述过程中,即使包含对称加密密钥的密文被第三方截获,第三方因为没有私钥,所以无法解密密文获取对称加密的密钥。这一过程看似没有问题,实则不然。在甲方传递公钥给乙方的过程中,如果第三方截获了公钥,并自己生成了新的公钥和私钥,然后把自己的公钥传递给乙方,乙方在收到第三方的公钥后(乙方不知情,他以为公钥是甲方给他的),生成对称加密的密钥,然后用公钥加密,并返回给甲方,这一过程又被第三方所截获,因为公钥是自己的,所以第三方可以用自己的私钥解密并获取对称加密的密钥。接着,第三方用之前截获的甲方的公钥,对对称加密的密钥进行加密并返回给甲方,因为公钥是甲方的,所以甲方可以成功用自己的私钥解密并获得密钥。这样,在甲乙双方不知情的情况下,第三方已经成功的获取到了双方通信时所使用的密钥了,如下图所示。那么问题来了,乙方在收到公钥后,如何确保这个公钥是甲方给他的呢?

这个问题就好比是有一天一个人跑过来和你说他是马云,他出来玩没带钱,如果你给他 100 块钱打车回家,他回去后给你 1 个亿。遇到这种情况,你如何能知道他就是马云呢?身份证拿出来看看!这基本是脱口而出的回答。那么要解决上述问题,甲方在发送公钥给乙方时,就还需要把自己的身份证给乙方看看。那甲方这个身份证如何来的呢?如何能确保身份证是不是真的呢?从现实生活中,我们可以得出答案。人民币由中国银行发行,所有人都承认人民币是有效地,并且人民币有特殊的制造工艺,具备防伪标识。

至此,显然只通过甲乙双方是无法建立安全通信的,需要一个第三方的权威机构介入,这个权威机构被称为 CA(Certificate Authority),在甲方申请后,CA 机构给甲方颁发“身份证”,甲方在发送公钥时连同自己的“身份证”一起发送给乙方,乙方通过核实“身份证”来确认公钥是否来自甲方。那么乙方如何核实“身份证”,并且如何确保“身份证”不会被伪造呢?这就需要一种只有 CA 能产出,并且所有乙方都能识别的机制,而非对称加密正好就满足这种一对多的机制。CA 机构通过自己的私钥对“身份证”进行加密生成密文,其中“身份证”被称为 数字证书,而密文则被称为 数字签名,然后将签名附加到证书中(签在底部),最后将经过签名后的证书颁发给甲方。于是,甲方在发送公钥时,连同证书一起发送给乙方,乙方在收到后,使用 CA 机构的公钥解密签名,对比签名的内容和证书内容是否相同即可验证甲方身份。那么问题又来了,乙方如何知道 CA 机构的公钥呢?显然如果继续通过网络传输的方式获取,这个问题可能永远都无法解决,而考虑到这样的权威机构可能只需要一个就够了,完全可以让乙方一开始就保留着该公钥,例如:浏览器内置 CA 机构的公钥。通过这样的机制,甲乙两方就能建立安全的通信了。具体关于 CA 证书的介绍以及它是如何证明公钥没有被篡改的,见我另外一篇博客

HTTPS 通信过程

前面在了解了 HTTPS 的原理之后,再来说说 HTTPS 的具体通信过程,HTTPS 通信的过程基本就是原理中提到的几个步骤,具体如下:

  1. 客户端向服务端 Say Hello,包含支持的 SSL 协议版本、加密算法、密钥长度等信息。
  2. 服务端响应客户端信息发送 Server Hello 报文,报文中包含确定的加密算法、密钥长度等信息。
  3. 服务端发送证书给客户端。
  4. 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的SSL握手协商部分结束。
  5. 客户端收到证书后,验证证书的有效性。如果证书无效,在浏览器上会提示;如果验证有效,发送 Client Key Exchange 报文给服务端,报文中包含被称为 Pre-master secret 的随机码,该随机码通过服务端证书中的公钥进行加密。
  6. 接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会使用 Pre-master secret 密钥加密。
  7. 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。如果服务器能解密出来,则握手成功。
  8. 服务端收到 Finished 报文并成功解密后,同样发送 Change Cipher Spec 报文和 Finished 报文给客户端。
  9. 成功建立安全连接,进行 HTTP 通信,底层通过 SSL 加密。
  10. 通信结束,发送报文关闭连接。
The End        Thank You