概述

公钥系统

公钥系统也被称为非对称密钥系统,最著名的是 RSA 算法。该系统包含一对关联的密钥对:一个公开的、用于加密的公钥和一个私有的、用于解密的私钥。公钥可以任意传播,所有人都能用它来加密原文得到密文,但密文只有私钥能进行解密得到原文。

但是公钥算法的加解密操作耗时远大于对称加密算法,因此公钥算法常用于通信双方交换对称密钥(握手阶段),而通信过程中对消息的加密和解密则使用对称加密算法。

加密与签名

公钥算法有些提供密钥分发和加密功能,有些提供数字签名功能,有些算法则提供以上两种功能,例如 RSA 算法。因此本文后续将 RSA 公钥的运算由狭义的“加密”改称为更广泛的 E运算,以及将私钥的运算由狭义的“解密”改称为更广泛的 D运算

对于明文 M (message), 使用公钥 Pub 进行E运算的过程和结果分别记作 E(Pub, M) = X₁,简写为 E(M) = X₁、使用私钥 Pri 进行D运算的过程和结果分别记作 D(Pri, M) = X₂,简写为 D(M) = X₂

由此可见所谓的D运算、E运算,本质上是使用相应的 key 作为参数,将消息 M 转换成一段不可读/意义不明的消息 X. 需要特别注意的是,两种运算的顺序是可以互换的,而且最终都可以将作为中间产物的密文 X 还原为原文 M:

D( E(M) ) = E( D(M) ) = M

先进行E运算(公钥)后进行D运算(私钥),则将该过程称为加密/解密。先进行D运算(私钥)后进行E运算(公钥),则将该过程称为签名/验签。

鉴别

在通信时进行鉴别,可防止多种网络攻击。鉴别的对象有报文和实体两种。报文鉴别需要在会话期间对每次通讯进行鉴别(多次),而实体鉴别只需要在创建连接时鉴定一次即可。

鉴别报文

对报文的鉴别主要有三个方面:防篡改、防窃听、防重放。

密码散列函数

散列函数又被称为哈希函数、hash 函数,是将输入通过哈希运算后得到固定长度的哈希值的函数。由于输出的长度是固定的,即输出结果是有限的集合(如128位散列函数,输出的组合有 2128种),而输入的长度是无限的,因此不同输入的计算结果可能是相同的,即发生了哈希碰撞。

消息鉴别码 MAC

消息鉴别码 (MAC, message authentification code) 是由原文映射而来的一小段数据,用于原文经过传输后,通过它来验证原文的完整性。通常由原文和一些辅助数据(类似盐值 Salt 的作用)作为参数,经过某种运算后得到。如果使用散列算法计算 MAC,则将该 MAC 称为 HMAC (Hash-based MAC).

接收方拿到原文 M 和校验码 MAC1 后,使用相同的运算方式得到 MAC2 后,只要两个 MAC 相同则表明消息没有遭到篡改。按照生成摘要的方式划分,有两种计算 MAC 的方式:

方法一:收发双方都有生成 MAC 的能力,则要求用于运算的参数中必须包含仅收发双方知道、第三方不可知的元素。典型的例子是收发双方预先约定好的密钥 Key 和具体的 hash 函数(约定好类型、版本和长度)。

1
2
3
4
5
6
7
8
发送方:待发送的数据为 Payloadₛ
1. 拼接载荷 Payloadₛ 和 密钥 Key 后进行 hash 运算,得到哈希值 HMAC => hash(Payloadₛ + Key) = HMACₛ
2. 拼接 Payloadₛ 和 HMACₛ 拼接为报文 Message => Payloadₛ + HMACₛ = Messageₛ

接收方:接收到报文 Messageᵣ
3. 根据 HMAC 的长度,从接收到的报文 Messageᵣ 中截取 Payloadᵣ 和 HMACᵣ => Messageᵣ = Payloadᵣ + HMACₛ
4. 重新计算当前 Payloadᵣ 对应的 HMAC => hash(Payloadᵣ) = HMACᵣ
5. 比较自行计算的 HMACᵣ 和 接收到的 HMACₛ,二者相同则消息未被篡改

假设原文被攻击者截获并尝试篡改,由于攻击者并不知道密钥 Key, 因此无法得知接收方会算出什么样的 HMAC, 而接收方发现 HMAC 的值不匹配就会警觉。换句话说,如果攻击者能计算出篡改后的 HMAC 值(例如知道了密钥 Key),则接收方将不会知道消息已被篡改。

方法二:接收方没有计算/生成 MAC 的能力,因此不需要使用额外的密钥 Key. 典型的例子是 RSA 算法,只有持有私钥的发送方能使用 D 运算,而持有公钥的多个接收方只能使用 E 运算。

1
2
3
4
5
6
7
8
9
10
发送方:待发送的数据为 Payloadₛ
1. 对 Payload 进行 hash 运算后得到哈希值 H => hash(Payloadₛ) = Hₛ
2. 用私钥对 H 进行 D 运算,得到 MAC => D(Pri, Hₛ) = MACₛ
3. 将 Payload 和 MAC 组合成报文 Messageₛ => Payloadₛ + MACₛ = Messageₛ

接收方:接收到报文 Messageᵣ
4. 按 MAC 的长度,分离出 Payload 和 MAC => Messageᵣ = Payloadᵣ + MACᵣ
5. 对 Payload 进行 hash 运算得到哈希值 H => hash(Payloadᵣ) = Hᵣ
6. 用公钥对接收到的 MACᵣ 进行 E 运算 => E(Pub, MACᵣ) = Hₛ
7. 对比摘要 Hᵣ 和 Hₛ,二者相同则表明 Payloadᵣ 没有被篡改

nonce

在加密通信中,nonce 是只使用一次的随机数,用于防止重放攻击。

TODO

鉴别实体

通信时进行实体鉴别,可防止中间人攻击。对实体的鉴别可双向进行,但在大部分情况下是客户端对服务器身份的鉴别。

TLS

协议 TLS (transport layer security) 用于防止窃听、篡改与伪造等网络攻击。TLS 位于 TCP 与应用层之间,向应用程序提供服务。HTTP 协议使用 TLS 服务时,即为 HTTPS, 即 HTTPS 是 TLS 服务集合中的一个子集。

握手协议

首要任务/目标:交换密钥、协商会话阶段所需的参数

  1. 协商加密算法
  2. 服务器鉴别
  3. 生成主密钥
  1. 密钥交换阶段
  2. 服务器参数:
  3. 鉴别:双向身份鉴别,但多数是客户端对服务器的鉴别。以及确认密钥、完成握手。

记录协议/会话过程

HTTPS证书

HTTPS证书是服务提供方的身份证明文件。服务提供方提供公钥、网站信息、拥有者身份等实体信息用于认证,由 CA 进行认证签名后增加 CA 信息、CA 签名。在 client - server 进行 TLS 通信过程时,server 会提供自己证书文件,client 可根据证书上的签发机构及其签名,使用 CA 的公钥对其进行校验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+--------------+
| 未签名的证书
+--------------+
| 服务器的基本信息
| 服务器的公钥
+--------------+
|
|
+--------------+

CA_x 使用自己的私钥为证书签名:
+------------------+
| 已签名的证书
+------------------+
| 服务器的基本信息
| 服务器的公钥
+------------------+
| 签发者:CA_x
| 签名:signature_x
+------------------+

证书链

数字证书认证中心 (Certificate Authority, CA) 的组织呈树状分布,位于顶部的 CA 为 Root CA. Root CA 可以授权多个下属的多层级 CA, HTTPS 证书的认证只要在任意一个 CA 认证成功,即为该 CA 到根 CA 证书链中的一环。

假设 CA 的关系为:CA_root → CA_1 → CA_2, cert_x 在 CA_2 上通过认证。则 cert_x 包含 CA_2 的签名,用户可以根据该签名找到 CA_2 的证书,其上有 CA_root 的签名。用户再根据 CA_root 的签名证实其为根 CA 的证书,即可证明 cert_x 为可信证书。根 CA 的证书为自签名证书,无需继续向上校验。

参考资料