下面把前面的内容重新整理成一份**完整总结**,并重点补充 AEAD 算法的数据传输过程示例与原理说明。
一、核心结论¶
如果目标只是保证数据完整性:
- 可以使用对称算法,但不能用“普通对称加密”来冒充签名。
- 正确做法是使用:
- MAC / HMAC:保证完整性和双方认证;
- AEAD:同时保证保密性和完整性。
- 如果需要:
- 向第三方证明;
- 公开验证;
- 防抵赖;
则必须使用**非对称数字签名**,例如 Ed25519、ECDSA、RSA-PSS、SM2。
一句话概括:
普通对称加密只负责保密,不负责完整性;AEAD 才是对称算法下同时解决保密性和完整性的标准方案。
二、数据完整性、认证、保密、防抵赖的区别¶
在密码学里,这几个概念不能混在一起:
| 安全目标 | 含义 | 典型技术 |
|---|---|---|
| 完整性 | 数据没有被意外或恶意篡改 | Hash、MAC、AEAD、签名 |
| 保密性 | 数据不能被未授权者读取 | 对称加密、非对称加密 |
| 来源认证 | 确认数据来自可信方 | MAC、AEAD、数字签名 |
| 不可否认性 | 发送方不能否认自己发送过数据 | 非对称数字签名 |
因此:
三、为什么普通对称加密不能保证完整性?¶
很多人会误以为:
数据都被 AES 加密了,攻击者改不了。
这是错误的。
普通加密模式,例如:
只保证数据“看不懂”,但不保证数据“没被改”。
攻击者即使不知道明文,也可能修改密文。例如在流密码或 CTR 模式下:
如果攻击者对密文某些比特做翻转:
接收方解密后会得到:
也就是说,攻击者虽然不知道明文,但可以精确修改明文中的某些位。
这就是为什么必须有完整性校验机制。
四、AEAD 是什么?¶
AEAD 的全称是:
它同时提供:
常见 AEAD 算法包括:
AEAD 的输出不是只有密文,而是:
通常还会发送:
五、AEAD 的基本原理¶
AEAD 内部一般由两部分组成:
可以抽象理解为:
但 AEAD 不是简单地把两个算法拼起来,而是经过标准化和安全证明的一体化设计。
1. 保密性从哪里来?¶
AEAD 使用对称密钥对明文加密。
例如:
没有密钥的人无法从密文恢复明文。
因此 AEAD 提供保密性。
2. 完整性从哪里来?¶
AEAD 会基于密钥生成一个认证标签:
这个 tag 会绑定:
接收方收到数据后,会重新计算 tag:
然后比较:
如果不相等,说明数据被篡改,接收方直接拒绝。
因此 AEAD 提供完整性。
3. 为什么攻击者改不了?¶
因为攻击者没有密钥。
攻击者可以修改:
但是他无法重新生成正确的:
因为 tag 依赖密钥:
没有 key,就无法伪造合法 tag。
所以只要 tag 验证通过,就可以认为:
六、AEAD 的数据传输过程示例¶
下面用一个完整例子说明 AEAD 在通信中的使用过程。
假设 Alice 要给 Bob 发送一条加密消息:
他们事先共享了一个对称密钥:
同时,每个消息会使用一个一次性数字:
另外,消息头中有一些字段不需要保密,但必须防止被篡改,例如:
这里的 aad 就是 Associated Data,关联数据。
步骤 1:Alice 准备数据¶
Alice 有以下输入:
key = 双方共享密钥
nonce = 消息唯一编号
plaintext = "transfer 100 USD to Bob"
aad = "from=Alice;to=Bob;seq=1001"
其中:
key不能传输;plaintext需要保密;aad可以明文传输,但必须防篡改;nonce可以明文传输,但同一密钥下不能重复。
步骤 2:Alice 调用 AEAD 加密¶
Alice 执行:
以 ChaCha20-Poly1305 为例,可以理解为:
ciphertext = ChaCha20_Encrypt(key, nonce, plaintext)
tag = Poly1305_MAC(key, nonce, aad, ciphertext)
以 AES-GCM 为例,可以理解为:
ciphertext = AES-CTR_Encrypt(key, nonce, plaintext)
tag = GHASH/GMAC(key, nonce, aad, ciphertext)
最终 Alice 得到:
步骤 3:Alice 发送消息¶
Alice 把以下内容发送给 Bob:
例如:
nonce = 0x0000000000000001
aad = "from=Alice;to=Bob;seq=1001"
ciphertext = 9f3a7c...
tag = e5b1f2...
注意:
步骤 4:Bob 收到消息¶
Bob 收到:
Bob 也拥有相同的密钥:
Bob 执行 AEAD 解密与验证:
步骤 5:Bob 先验证 tag¶
AEAD 的正确实现不会先解密再验证,而是:
Bob 会重新计算:
然后比较:
如果相等:
如果不相等:
步骤 6:验证成功,解密成功¶
如果 tag 验证通过,Bob 解密得到:
此时 Bob 可以确认:
七、AEAD 传输过程中的篡改场景示例¶
下面看攻击者 Eve 可能做什么。
场景 1:Eve 修改密文¶
原始消息:
Eve 修改密文:
但是 Eve 不知道 key,无法生成新的合法 tag。
Bob 收到后:
验证失败。
结果:
场景 2:Eve 修改 aad¶
例如把:
改成:
虽然 aad 是明文,但 tag 计算时覆盖了 aad。
所以 Bob 重新计算 tag 时会发现:
验证失败。
结果:
这就是 Associated Data 的作用:
不加密,但保证不能被篡改。
场景 3:Eve 修改 nonce¶
如果 Eve 修改 nonce:
由于 tag 也绑定 nonce,验证同样会失败。
结果:
场景 4:Eve 重放旧消息¶
Eve 没有修改任何内容,只是把之前的合法消息再发送一次:
从 AEAD 算法本身看,tag 仍然合法。
因此:
要防重放,需要应用层检查:
例如 Bob 发现:
则拒绝该消息。
场景 5:Eve 伪造全新消息¶
Eve 想自己构造:
但 Eve 没有 key,无法生成合法的:
因此无法伪造能通过验证的消息。
八、AEAD 为什么能同时满足保密性和完整性?¶
可以用一句话概括:
加密保证别人看不懂,Tag 保证别人改不了。
更详细地说:
保密性:
使用 key 和 nonce 对 plaintext 加密,
没有 key 的人无法恢复明文。
完整性:
使用 key 对 ciphertext、aad、nonce 等计算 tag,
没有 key 的人无法伪造合法 tag。
接收方策略:
只有 tag 验证成功,才允许解密。
一旦数据被篡改,解密过程会失败。
所以 AEAD 同时满足:
九、以 AES-GCM 为例说明原理¶
AES-GCM 是典型的 AEAD 算法。
它由两部分组成:
简化流程如下:
1. 使用 key 和 nonce 生成计数器;
2. 使用 AES-CTR 加密 plaintext,得到 ciphertext;
3. 使用 GHASH 对 aad、ciphertext、长度信息等计算认证摘要;
4. 使用 AES 加密某个计数器值,生成最终 tag;
5. 输出 ciphertext 和 tag。
接收方:
AES-GCM 的安全性高度依赖:
尤其是 AES-GCM,在同一 key 下重复使用 nonce 可能导致严重安全问题。
十、以 ChaCha20-Poly1305 为例说明原理¶
ChaCha20-Poly1305 也是常见 AEAD。
它由两部分组成:
简化流程:
1. 使用 key 和 nonce 生成一次性 Poly1305 密钥;
2. 使用 ChaCha20 加密 plaintext,得到 ciphertext;
3. 使用 Poly1305 对 aad、ciphertext 等计算 tag;
4. 输出 ciphertext 和 tag。
接收方:
ChaCha20-Poly1305 在移动端、软件实现中很常见,性能通常很好。
十一、AEAD 中的 Associated Data 很重要¶
AEAD 里的 A 是:
它表示:
常见例子:
例如:
这些内容如果加密,接收方可能无法处理。
但是如果不保护,攻击者可能篡改。
AEAD 的做法是:
这就是 AEAD 中 Associated Data 的价值。
十二、AEAD 的安全边界¶
虽然 AEAD 很强,但它不是万能的。
1. AEAD 不能防抵赖¶
因为 AEAD 使用对称密钥。
Alice 和 Bob 都有同一个 key。
如果 Alice 给 Bob 发了一条消息,Bob 可以验证消息合法。
但 Bob 无法向第三方证明这条消息一定是 Alice 发的,因为 Bob 自己也有 key,也可以生成合法消息。
如果需要防抵赖,要用数字签名:
例如:
2. AEAD 不能自动防重放¶
AEAD 只能判断:
但它不能自动判断:
防重放需要应用层机制:
3. AEAD 对 nonce 要求很高¶
AEAD 通常需要:
同一个 key 下,nonce 通常不能重复。
尤其对于 AES-GCM:
可能影响包括:
推荐做法:
4. AEAD 不解决密钥分发问题¶
AEAD 是对称算法,通信双方必须共享同一个 key。
因此问题变成:
常见方案:
如果密钥泄露,AEAD 的保密性和完整性都会失效。
十三、AEAD 与普通数字签名的关系总结¶
可以这样理解:
对应关系:
| 能力 | AEAD | 数字签名 |
|---|---|---|
| 保密性 | 通常有 | 无,除非额外加密 |
| 完整性 | 有 | 有 |
| 来源认证 | 有,但仅限共享密钥双方 | 有 |
| 第三方验证 | 无 | 有 |
| 防抵赖 | 无 | 有 |
| 性能 | 高 | 相对较低 |
| 密钥类型 | 对称密钥 | 非对称密钥 |
十四、完整示例:Alice 给 Bob 发送安全消息¶
最终完整流程如下:
前提:
Alice 和 Bob 共享对称密钥 key。
双方约定使用 AEAD 算法,例如 ChaCha20-Poly1305。
发送方 Alice:
1. 生成唯一 nonce;
2. 准备明文 plaintext;
3. 准备关联数据 aad;
4. 调用 AEAD_Encrypt;
5. 得到 ciphertext 和 tag;
6. 发送 nonce || aad || ciphertext || tag。
接收方 Bob:
1. 收到 nonce || aad || ciphertext || tag;
2. 检查 nonce 是否重复,防重放;
3. 调用 AEAD_Decrypt;
4. AEAD 内部重新计算 tag;
5. 如果 tag 不匹配,直接失败;
6. 如果 tag 匹配,解密密文,得到 plaintext;
7. 处理业务。
伪代码:
# Alice
nonce = next_nonce()
aad = "from=Alice;to=Bob;seq=1001"
plaintext = "transfer 100 USD to Bob"
ciphertext, tag = AEAD_Encrypt(
key=key,
nonce=nonce,
plaintext=plaintext,
aad=aad
)
send(nonce, aad, ciphertext, tag)
# Bob
nonce, aad, ciphertext, tag = receive()
if nonce_is_reused(nonce):
reject()
try:
plaintext = AEAD_Decrypt(
key=key,
nonce=nonce,
ciphertext=ciphertext,
tag=tag,
aad=aad
)
except:
reject()
process(plaintext)
十五、最终总结¶
完整总结如下:
1. 如果只是防意外损坏:
使用普通哈希,例如 SHA-256。
2. 如果要防恶意篡改,且双方共享密钥:
使用 HMAC / MAC,例如 HMAC-SHA256。
3. 如果既要保密,又要保证完整性:
使用 AEAD,例如 AES-GCM 或 ChaCha20-Poly1305。
4. 如果要公开验证、防抵赖:
使用非对称数字签名,例如 Ed25519、ECDSA、RSA-PSS、SM2。
AEAD 的核心原理是:
因此:
AEAD 能同时满足保密性和完整性,是因为它把“加密”和“带密钥认证”结合成一个安全整体:加密让别人看不见,Tag 让别人改不了。