为什么需要 HTTPS?

如今,HTTPS 已经渐渐成为主流,很多大型网站都已经全站 HTTPS 化。那么有了 HTTP 后为什么还需要有 HTTPS 呢?——为了解决 HTTP 的不足。

HTTP 的不足之处

  • 通信内容使用明文——内容可能被窃听
  • 不验证通信方的身份——可能遭遇伪装
  • 无法验证报文的完整性——报文有可能已遭篡改

怎样解决 HTTP 的不足之处?

(一)解决内容为明文问题——加密

公开密钥加密

公开密钥加密(Public-key cryptography) 是一种具备以下特征的加密方式:

  • 使用公开的加密算法
  • 秘钥是保密的
  • 使用密钥来进行加密和解密

也就意味着任何人只要得到了密钥,就能进行密钥。秘钥如果泄漏,加密就失去了意义。

公开密钥加密分为对称密钥加密和非对称密钥加密:

对称秘钥加密

加密和解密双方使用同一个密钥的方式叫做对称密钥加密。这种方式最大的问题是怎样把密钥安全的从一方发送给另一方,由于网络本身就是不安全的,因此无法保证密钥在发送过程中不会被人截获,任何人只要获得了密钥就能随便解密了。当然也可以不通过网络来发送,比如在线下用 U 盘拷给别人,或者口头告诉别人,在某些场景下这种方式是可以的,但是对于 HTTP 网络请求就无能为力了。

非对称秘钥加密

非对称密钥加密解决了密钥在网络上发送的安全问题。非对称秘钥加密使用一对秘钥,一把叫做私有秘钥(private key),另一把叫做公开秘钥(public key)。私钥不能让其他任何人知道,而公钥可以随意发布,任何人都能获得。

私钥只保管在解密的一方,公钥会被发送给加密的一方。使用这种方式时,发送密文的一方会使用对方公开的公钥对数据进行加密,对方收到加密数据后,再使用自己的私钥进行解密。由于能解密的只有私钥,而私钥不用再网络上发送,因此不用担心被盗走。

另外,非对称秘钥加密中,攻击者得到了公钥和密文,想破解出原文,就目前的技术来看是非常困难的,因此也保证了数据的安全。

(二)解决报文完整性问题——数字签名

数字签名是用来确保数据完整性的技术,它可以证明数据是来自谁,证明数据是否未被篡改过。

数字签名是附加在数据上的一段特殊的加密过的校验码,使用数字签名有以下几个好处:

  • 数字签名可以证明数据的作者是谁。因为数字签名是由数据作者用只有作者本人才知道的私钥生成的校验和,因此,这些校验和就像来自于作者的个人“签名”一样。

  • 数字签名可以防止数据被篡改。如果数据被篡改过,校验和就不匹配了。由于校验和只有作者的保密的私钥才能产生,攻击者在没有私钥的情况下,以目前的技术还无法为篡改后的数据伪造出正确的校验和。

下面看一下数字签名在网络数据传输中的一个应用流程:

假设有节点 A 要向节点 B 发送一段报文:

  1. 节点A为要发送的报文生成摘要(例如md5)
  2. 节点A用自己的私钥对摘要执行签名函数生成数字签名
  3. 节点A把数字签名附在要发送的报文之后,然后把报文和签名一块发送给节点B
  4. 节点B收到报文后,先取出数字签名部分,用公钥对签名执行反签名函数得到摘要
  5. 节点B对报文部分生成摘要(例如md5)
  6. 节点B对 4、5 两个步骤得到的两个摘要进行比较
  7. 如果一致,则可以认为报文是未被篡改过的

(三)解决通信对方可能被伪装的问题——认证

有了数字签名,就可以验证数据的来源和完整性了,但是仅有数字签名还是有漏洞。使用数字签名进行加密数据传输,数据接收方必须有一个公钥,如果这个公钥被篡改为了攻击者的公钥,那攻击者就可以用自己的私钥发送篡改后的数据了。

为了保证公钥的真实性,引入了认证这一手段。

数字证书

数字证书,有点像生活中的身份证、护照等,是由一个官方的证书颁发机构签发的一组数据。这种证书很难伪造,用于使用者的身份证明。

数字证书包含以下内容:

  • 证书格式版本号
  • 证书序列号
  • 过期时间
  • 证书办法机构
  • 证书使用的签名算法
  • 过期时间
  • 对象名称(人、服务器、组织、公司等)
  • 对象的公开密钥
  • 其它扩展信息
  • =====================
  • 附上证书颁发机构的数字签名

证书对服务器进行认证:

对服务器进行认证时,数字证书中的 对象名称 字段就是服务器的名称和主机名,对象的公开密钥 字段就是服务器的公开密钥。

客户端或浏览器与服务器通信时会进行如下流程:

  • 建立 SSL 连接时,服务器会把自己的数字证书下发给客户端/浏览器
  • 客户端/浏览器通过证书中 证书颁发机构的数字签名 来验证证书的来源和完整性。一般客户端/浏览器会内置一个受信任的证书颁发机构列表。
  • 一旦证书被认证通过,客户端/浏览器就从证书中取出 对象的公开密钥,用这个公钥来加密数据和服务端进行通信了。

HTTPS = HTTP + 加密 + 数字签名 + 认证

现在来看看 HTTPS 到底是个啥。

HTTPS = HTTP + SSL

SSL(Secure Sockets Layer,安全套接层),诞生于上世纪 90 年代的网景公司,后来又出现了 SSL 的改进版 TLS(Transport Layer Security,传输层安全协议)。所以目前主要用的是 TLS,不过习惯上还是统一叫做 SSL。SSL 主要内容就是加密、数字签名和认证机制,所以:

SSL = 加密 + 数字签名 + 认证

因此:HTTPS = HTTP + 加密 + 数字签名 + 认证

SSL 的加密机制

上面说过了对称秘钥加密和非对称秘钥加密,SSL 的加密是把这两种加密方式混合起来用的。

由于非对称秘钥加密的性能比对称秘钥加密要慢,只有在建立 SSL 安全连接时,使用非对称秘钥加密,在 SSL 安全连接建立成功后,这时已经能保证通信线路上的数据不会被窃取了,后面都会使用对称秘钥加密。

建立 SSL 安全连接前:

非对称密钥加密非对称密钥加密客户端服务器

建立 SSL 安全连接后:

对称秘钥加密对称秘钥加密客户端服务器

SSL 的数字签名机制

SSL 的数字签名和上面说到的数字签名基本一致。就是先通过报文得到摘要,把摘要用自己这边的密钥加密后得到数字签名,对方收到后,取出数字签名用自己的密钥反签名后得到摘要,和通过报文得到的摘要进行比对,如果一致的话就代表验证通过了完整性。

SSL 的认证技术

作为服务端想使用 HTTPS,会去官方的正规的证书颁发机构申请证书,需要花点费用。然后服务端会把自己的公钥放在证书里发给服务端,用证书来保证公钥的来源是真实可信的。

一次完整的 HTTPS 的通信步骤

步骤 1:客户端向服务器发送 ClientHello 报文,请求建立 SSL 连接。

ClientHello 报文:

  • 客户端支持的 SSL 版本
  • 客户端支持的加密算法
  • 客户端支持的密钥长度

步骤 2:服务器收到客户端的请求后,向客户端发送 ServerHello 报文。

ServerHello 报文:

  • 决定使用的 SSL 版本
  • 决定使用的加密算法

步骤 3:服务器继续发送 Certificate 报文,即服务器的数字证书,其中包含服务器的公开密钥。

步骤 4:服务器发送 ServerHelloDone 报文,通知客户端进最初阶段的 SSL 握手协商部分结束。

步骤 5:客户端收到以上所有信息后,发送 ClientKeyExchange 报文作为回应。该报文已使用步骤 3 中的公开密钥加密。其中包含一种称为 Pre-master secret 的随机密码串,用于之后的对称秘钥加密通信。

步骤 6:客户端继续发送 ChangeCipherSpec 报文,该报文告诉服务器,在此之后的通信都会采用步骤 5 中的 Pre-master secret 秘钥加密。

步骤 7:客户端发送 Finished 报文。改报文包含连接至今全部报文的整体校验值。

步骤 8:服务端对客户端报文校验后,同样发送 ChangeCipherSpec 报文,含义与步骤 6 中的相同。

步骤 9:服务端发送 Finished 报文。

步骤 10:服务端和客户端的 Finished 报文交换完毕后,SSL 连接建立完成。从此后开始进行应用层协议的通信,即 HTTP 通信。

步骤 11:HTTP 通信。

步骤 12:客户端发送 close_notify 报文请求断开连接。之后再发送 TCP FIN 报文来关闭 TCP 通信。

HTTPS 性能考虑

从上面的步骤可见,一次 HTTPS 连接会比一次单纯的 HTTP 连接做很多额外的事情。因此 HTTPS 的性能开销是比 HTTP 大很多的。考虑到性能这一块,可以在某些对安全要求比较高的场景使用 HTTPS,比如涉及到钱和支付,在一些对安全要求并不高的场景使用性能更好的 HTTP。

随着科技的进步,机器的性能越来越好,人们对安全的需求会比性能更加重要,因此安全的 HTTPS 会渐渐的代替 HTTP。

参考资料

  • 《图解 HTTP》
  • 《HTTP 权威指南》