之前有粗略了解过 HTTPS 加密的过程,比如对称加密、非对称加密、数字证书等等。但还是会被拷打的底裤不剩,所以认真总结一波。

# 为什么需要 HTTPS

HTTP 是一种超文本传输协议,它是明文的,也就代表如果客户端的请求被中间人抓包,可以篡改中间的数据再发往服务器,服务器无法判断数据是否被人为修改过。

弊端如下:

  • 无法保证消息的保密性
  • 无法保证消息的准确性
  • 无法保证消息的来源

# 基本概念

# 对称加密

客户端与服务器可以协商一份密钥,使用这个密钥对发送的消息进行加密,再对接收到的信息做解密。看起来可以确保消息的保密性。

但它存在一个缺点:这个密钥是共享的,交换过程容易存在风险 -> 密钥泄漏。

# 非对称加密

上面说到密钥容易泄漏,有一种解决方案是:使用公钥加密的信息只能被私钥解密,反过来使用私钥加密的信息也只能被公钥解开。于是客户端可以使用公钥加密发送的信息,服务器再使用私钥解密。

因此服务器可以预先发送给客户端一份公钥,客户端需要发送对称密钥时使用这个公钥加密后再发送给服务器,只有服务器能用私钥解密出里面具体的对称密钥,随后他们使用这个对称密钥进行通信。

这样看来好像使交换过程比较安全,因为即使公钥是可知的,也无法把消息进行解密。

# 中间人攻击

上面的非对称加密已经在较大程度上保证了消息的保密性。因为只有对应的私钥才能解开对应公钥加密的信息。

但还是因为公钥是公开的,可以会存在下面这个场景:

A 是服务器,B 是客户端,C 是中间人。Pub 代表公钥,Priv 代表私钥,Session 代表对称密钥。

  1. 公钥替换
  • A 发送一份公钥 Pub_A 给 B,C 拦截了这份请求,并把公钥替换为 Pub_C 再发送给 B。
  • B 收到请求中的公钥 Pub_C,以为这就是 A 的公钥,便开始使用 Pub_C 加密信息并发送。
  1. 解密并转发
  • 当 B 发送密钥并通过 Pub_C 加密时,C 拦截请求并使用自己的私钥 Priv_C 解密出对称密钥 Session。
  • 此时 C 已经知晓了 Session,他继续使用 Pub_A 加密这份 Session 发送给 A。
  • A 收到一份 Pub_A 加密的消息,理所当然地进行解密出 Session,这时双方就可以使用 Session 进行通信了。
  1. 后续通信
  • 现在不仅 A、B 拥有 Session,中间人 C 也拥有 Session,C 就可以随时对消息体进行解密篡改再加密。

# 数字证书与数字签名

中间人攻击的本质是公钥来源不可信,所以有一些专门的权威机构来颁发数字证书,称为 CA。服务器可以向 CA 申请一份属于自己的证书。

申请的过程如下:

  • 服务器生成一份公钥以及自己的企业信息之类,去 CA 申请数字证书。
  • CA 收到信息后会选择一种单向 Hash 算法(MD5)对这些信息做一个加密,加密后的数据称为摘要。
  • 这种加密算法是单向的,很大程度上不会被逆向解析。
  • 生成摘要后 CA 还会使用自己私钥对其进行加密,加密后的数据称为数字签名。
  • 最后 CA 会把服务器的企业信息、公钥、数字签名整合到一起,就叫做数字证书。

证书起作用的过程如下:

  • 服务器将数字证书发送给客户端,上面说到 CA 对摘要使用了自己的私钥加密,那么客户端就需要获取 CA 的公钥对其的数字签名进行解密。
  • 客户端是如何获取 CA 的公钥的:电脑和浏览器已经内置了一部分权威机构的根证书,这些根证书中包含了 CA 的公钥。
  • 客户端使用 CA 公钥对其数字签名进行解密,如果解密成功,代表证书来源是一个合法认证机构。
  • 对数字签名解密出摘要后,客户端结合证书中包含的企业信息、公钥,采用跟 CA 一样的单向 Hash 算法再对这些信息做一次加密,对比加密后的数据与原摘要是否一致,如果一致则说明未被篡改。
  • 至此,服务器就可以安全地向客户端传输公钥。

为什么可以避免中间人攻击?

上面的中间人攻击在于其替换了真实的公钥,而现在如果在证书中篡改了公钥,客户端使用单向 Hash 算法计算出的新摘要将会与原摘要不同,从而发现伪造身份。

# 加密结合

上面提到的非对称加密存在的隐患已经被数字证书解决,它还有个缺点就是性能相比普通的对称加密慢上几倍。所以在后续的信息交换中,HTTPS 还是会使用对称密钥进行通信,而对称密钥的交换使用非对称加密 + 数字证书完成。

# TLS/SSL 握手过程

上面的概念都是为了 TLS/SSL 所服务的,真实的 TLS/SSL 过程还包含了更多步骤以加强安全性。

  1. 客户端问候
  • 客户端发送一个 ClientHello 信息,里面包含了:
    • 支持的 TLS/SSL 版本
    • 支持的密码套件版本
    • 一个随机数记为 Client Random(后续加密需要使用)
    • 会话 ID(用于会话恢复时使用)
  1. 服务器响应
  • 服务器回复一个 ServerHello 信息,里面包含了:
    • 选择的 TLS/SSL 版本
    • 选择的密码套件版本
    • 一个随机数记为 Server Random (后续加密需要使用)
  • 同时,服务器还需要发送自己的数字证书
  • 最后,服务器发送 ServerHelloDone 信息,表示他的信息已经发送完毕
  1. 客户端验证身份
  • 客户端使用 CA 公钥对数字证书的数字签名进行解密
  • 客户端使用证书中的信息、公钥重新 Hash 看是否和解密后的摘要相同
  1. 双方确认密钥
  • 客户端生成一个随机数使用服务器公钥加密,叫做预主密钥 Pre-master secret。
  • 服务器收到 Pre-master secret 后用私钥解密。
  • 客户端和服务器各自计算最后的主密钥 Master Secret = PRF (Pre-master secret, “master secret”, Client Random, Server Random)
    • 参数 "master secret":固定的标签字符串(区分用途)
    • 作用:主密钥作为生成会话密钥的基础。
  • 客户端和服务器各自计算最后的会话密钥 Session Key = PRF (Master Secret, “key expansion”, Client Random + Server Random)
    • 参数 "key expansion": 固定的标签字符串(区分用途)
    • 参数 "Master Secret": 上面的主密钥
  1. 开始通信
  • 双方发送 Change Cipher Spec 和 Finished 报文
  • 表示后面的消息都使用会话密钥通信,并且已经成功生成了会话密钥

为什么需要分两步生成密钥?

Master Secret 作为中间层,防止 Pre-Master Secret 直接暴露给会话密钥。即使会话密钥泄露,也无法反向推导出 Pre-Master Secret。

更新于

请我喝[茶]~( ̄▽ ̄)~*

imtangx 微信支付

微信支付

imtangx 支付宝

支付宝

imtangx 贝宝

贝宝