跳转至

下面把前面的内容重新整理成一份**完整总结**,并重点补充 AEAD 算法的数据传输过程示例与原理说明。


一、核心结论

如果目标只是保证数据完整性:

  1. 可以使用对称算法,但不能用“普通对称加密”来冒充签名。
  2. 正确做法是使用:
  3. MAC / HMAC:保证完整性和双方认证;
  4. AEAD:同时保证保密性和完整性。
  5. 如果需要:
  6. 向第三方证明;
  7. 公开验证;
  8. 防抵赖;

则必须使用**非对称数字签名**,例如 Ed25519、ECDSA、RSA-PSS、SM2。

一句话概括:

普通对称加密只负责保密,不负责完整性;AEAD 才是对称算法下同时解决保密性和完整性的标准方案。


二、数据完整性、认证、保密、防抵赖的区别

在密码学里,这几个概念不能混在一起:

安全目标 含义 典型技术
完整性 数据没有被意外或恶意篡改 Hash、MAC、AEAD、签名
保密性 数据不能被未授权者读取 对称加密、非对称加密
来源认证 确认数据来自可信方 MAC、AEAD、数字签名
不可否认性 发送方不能否认自己发送过数据 非对称数字签名

因此:

Text Only
只防意外损坏:SHA-256 足够
防恶意篡改:HMAC / MAC
防篡改 + 防偷窥:AEAD
防篡改 + 公开验证 + 防抵赖:数字签名

三、为什么普通对称加密不能保证完整性?

很多人会误以为:

数据都被 AES 加密了,攻击者改不了。

这是错误的。

普通加密模式,例如:

Text Only
AES-CBC
AES-CTR

只保证数据“看不懂”,但不保证数据“没被改”。

攻击者即使不知道明文,也可能修改密文。例如在流密码或 CTR 模式下:

Text Only
ciphertext = plaintext XOR keystream

如果攻击者对密文某些比特做翻转:

Text Only
ciphertext' = ciphertext XOR delta

接收方解密后会得到:

Text Only
plaintext' = plaintext XOR delta

也就是说,攻击者虽然不知道明文,但可以精确修改明文中的某些位。

这就是为什么必须有完整性校验机制。


四、AEAD 是什么?

AEAD 的全称是:

Text Only
Authenticated Encryption with Associated Data
带关联数据的认证加密

它同时提供:

Text Only
保密性
完整性
认证性
关联数据保护

常见 AEAD 算法包括:

Text Only
AES-GCM
AES-CCM
ChaCha20-Poly1305
AES-OCB
AES-GCM-SIV

AEAD 的输出不是只有密文,而是:

Text Only
密文 ciphertext
认证标签 tag

通常还会发送:

Text Only
nonce
associated data

五、AEAD 的基本原理

AEAD 内部一般由两部分组成:

Text Only
加密模块:负责保密
认证模块:负责完整性

可以抽象理解为:

Text Only
AEAD = 对称加密 + 带密钥的完整性校验

但 AEAD 不是简单地把两个算法拼起来,而是经过标准化和安全证明的一体化设计。


1. 保密性从哪里来?

AEAD 使用对称密钥对明文加密。

例如:

Text Only
ciphertext = Encrypt(key, nonce, plaintext)

没有密钥的人无法从密文恢复明文。

因此 AEAD 提供保密性。


2. 完整性从哪里来?

AEAD 会基于密钥生成一个认证标签:

Text Only
tag = MAC(key, ciphertext, nonce, associated_data, ...)

这个 tag 会绑定:

Text Only
密文
nonce
关联数据
算法上下文
长度信息

接收方收到数据后,会重新计算 tag:

Text Only
expected_tag = MAC(key, received_ciphertext, received_nonce, received_aad, ...)

然后比较:

Text Only
expected_tag == received_tag ?

如果不相等,说明数据被篡改,接收方直接拒绝。

因此 AEAD 提供完整性。


3. 为什么攻击者改不了?

因为攻击者没有密钥。

攻击者可以修改:

Text Only
ciphertext
nonce
associated data

但是他无法重新生成正确的:

Text Only
tag

因为 tag 依赖密钥:

Text Only
tag = F(key, data)

没有 key,就无法伪造合法 tag。

所以只要 tag 验证通过,就可以认为:

Text Only
数据没有被篡改;
数据来自拥有该密钥的一方。

六、AEAD 的数据传输过程示例

下面用一个完整例子说明 AEAD 在通信中的使用过程。

假设 Alice 要给 Bob 发送一条加密消息:

Text Only
plaintext = "transfer 100 USD to Bob"

他们事先共享了一个对称密钥:

Text Only
key

同时,每个消息会使用一个一次性数字:

Text Only
nonce

另外,消息头中有一些字段不需要保密,但必须防止被篡改,例如:

Text Only
aad = "from=Alice;to=Bob;seq=1001"

这里的 aad 就是 Associated Data,关联数据。


步骤 1:Alice 准备数据

Alice 有以下输入:

Text Only
key       = 双方共享密钥
nonce     = 消息唯一编号
plaintext = "transfer 100 USD to Bob"
aad       = "from=Alice;to=Bob;seq=1001"

其中:

  • key 不能传输;
  • plaintext 需要保密;
  • aad 可以明文传输,但必须防篡改;
  • nonce 可以明文传输,但同一密钥下不能重复。

步骤 2:Alice 调用 AEAD 加密

Alice 执行:

Text Only
ciphertext, tag = AEAD_Encrypt(key, nonce, plaintext, aad)

以 ChaCha20-Poly1305 为例,可以理解为:

Text Only
ciphertext = ChaCha20_Encrypt(key, nonce, plaintext)
tag        = Poly1305_MAC(key, nonce, aad, ciphertext)

以 AES-GCM 为例,可以理解为:

Text Only
ciphertext = AES-CTR_Encrypt(key, nonce, plaintext)
tag        = GHASH/GMAC(key, nonce, aad, ciphertext)

最终 Alice 得到:

Text Only
ciphertext
tag

步骤 3:Alice 发送消息

Alice 把以下内容发送给 Bob:

Text Only
nonce || aad || ciphertext || tag

例如:

Text Only
nonce      = 0x0000000000000001
aad        = "from=Alice;to=Bob;seq=1001"
ciphertext = 9f3a7c...
tag        = e5b1f2...

注意:

Text Only
aad 是明文;
nonce 是明文;
ciphertext 是密文;
tag 是认证标签。

步骤 4:Bob 收到消息

Bob 收到:

Text Only
nonce'
aad'
ciphertext'
tag'

Bob 也拥有相同的密钥:

Text Only
key

Bob 执行 AEAD 解密与验证:

Text Only
plaintext = AEAD_Decrypt(key, nonce', ciphertext', tag', aad')

步骤 5:Bob 先验证 tag

AEAD 的正确实现不会先解密再验证,而是:

Text Only
先验证 tag,验证成功后才解密。

Bob 会重新计算:

Text Only
expected_tag = MAC(key, nonce', aad', ciphertext')

然后比较:

Text Only
expected_tag == tag' ?

如果相等:

Text Only
验证通过
继续解密
得到 plaintext

如果不相等:

Text Only
验证失败
直接丢弃
不输出明文

步骤 6:验证成功,解密成功

如果 tag 验证通过,Bob 解密得到:

Text Only
plaintext = "transfer 100 USD to Bob"

此时 Bob 可以确认:

Text Only
1. 消息内容没有被篡改;
2. aad 没有被篡改;
3. nonce 没有被篡改;
4. 消息来自拥有 key 的一方;
5. 明文是可信的。

七、AEAD 传输过程中的篡改场景示例

下面看攻击者 Eve 可能做什么。


场景 1:Eve 修改密文

原始消息:

Text Only
nonce || aad || ciphertext || tag

Eve 修改密文:

Text Only
ciphertext' = ciphertext 的某些比特被翻转

但是 Eve 不知道 key,无法生成新的合法 tag。

Bob 收到后:

Text Only
expected_tag != tag'

验证失败。

结果:

Text Only
Bob 拒绝消息,不解密。

场景 2:Eve 修改 aad

例如把:

Text Only
from=Alice;to=Bob;seq=1001

改成:

Text Only
from=Alice;to=Eve;seq=1001

虽然 aad 是明文,但 tag 计算时覆盖了 aad。

所以 Bob 重新计算 tag 时会发现:

Text Only
expected_tag != tag'

验证失败。

结果:

Text Only
Bob 拒绝消息。

这就是 Associated Data 的作用:

不加密,但保证不能被篡改。


场景 3:Eve 修改 nonce

如果 Eve 修改 nonce:

Text Only
nonce' != nonce

由于 tag 也绑定 nonce,验证同样会失败。

结果:

Text Only
Bob 拒绝消息。

场景 4:Eve 重放旧消息

Eve 没有修改任何内容,只是把之前的合法消息再发送一次:

Text Only
nonce || aad || ciphertext || tag

从 AEAD 算法本身看,tag 仍然合法。

因此:

Text Only
AEAD 不能自动防重放。

要防重放,需要应用层检查:

Text Only
seq 是否重复
nonce 是否已经使用过
timestamp 是否过期
challenge-response 是否新鲜

例如 Bob 发现:

Text Only
seq=1001 已经处理过

则拒绝该消息。


场景 5:Eve 伪造全新消息

Eve 想自己构造:

Text Only
plaintext = "transfer 10000 USD to Eve"

但 Eve 没有 key,无法生成合法的:

Text Only
ciphertext, tag

因此无法伪造能通过验证的消息。


八、AEAD 为什么能同时满足保密性和完整性?

可以用一句话概括:

加密保证别人看不懂,Tag 保证别人改不了。

更详细地说:

Text Only
保密性:
    使用 key 和 nonce 对 plaintext 加密,
    没有 key 的人无法恢复明文。

完整性:
    使用 key 对 ciphertext、aad、nonce 等计算 tag,
    没有 key 的人无法伪造合法 tag。

接收方策略:
    只有 tag 验证成功,才允许解密。
    一旦数据被篡改,解密过程会失败。

所以 AEAD 同时满足:

Text Only
保密性
完整性
认证性

九、以 AES-GCM 为例说明原理

AES-GCM 是典型的 AEAD 算法。

它由两部分组成:

Text Only
AES-CTR:加密
GHASH/GMAC:认证

简化流程如下:

Text Only
1. 使用 key 和 nonce 生成计数器;
2. 使用 AES-CTR 加密 plaintext,得到 ciphertext;
3. 使用 GHASH 对 aad、ciphertext、长度信息等计算认证摘要;
4. 使用 AES 加密某个计数器值,生成最终 tag;
5. 输出 ciphertext 和 tag。

接收方:

Text Only
1. 用相同 key 和 nonce 重新计算 tag;
2. 比较 tag;
3. tag 正确后才解密 ciphertext。

AES-GCM 的安全性高度依赖:

Text Only
key 保密;
nonce 不重复。

尤其是 AES-GCM,在同一 key 下重复使用 nonce 可能导致严重安全问题。


十、以 ChaCha20-Poly1305 为例说明原理

ChaCha20-Poly1305 也是常见 AEAD。

它由两部分组成:

Text Only
ChaCha20:流密码,负责加密
Poly1305:MAC,负责认证

简化流程:

Text Only
1. 使用 key 和 nonce 生成一次性 Poly1305 密钥;
2. 使用 ChaCha20 加密 plaintext,得到 ciphertext;
3. 使用 Poly1305 对 aad、ciphertext 等计算 tag;
4. 输出 ciphertext 和 tag。

接收方:

Text Only
1. 重新计算 tag;
2. 验证 tag;
3. 验证成功后解密。

ChaCha20-Poly1305 在移动端、软件实现中很常见,性能通常很好。


十一、AEAD 中的 Associated Data 很重要

AEAD 里的 A 是:

Text Only
Associated Data
关联数据

它表示:

Text Only
不需要加密,但需要防篡改的数据。

常见例子:

Text Only
协议版本号
包头
序列号
时间戳
路由信息
用户 ID
请求 ID

例如:

Text Only
aad = "version=1;from=Alice;to=Bob;seq=1001"

这些内容如果加密,接收方可能无法处理。

但是如果不保护,攻击者可能篡改。

AEAD 的做法是:

Text Only
aad 明文传输;
tag 绑定 aad;
一旦 aad 被改,tag 验证失败。

这就是 AEAD 中 Associated Data 的价值。


十二、AEAD 的安全边界

虽然 AEAD 很强,但它不是万能的。


1. AEAD 不能防抵赖

因为 AEAD 使用对称密钥。

Alice 和 Bob 都有同一个 key。

如果 Alice 给 Bob 发了一条消息,Bob 可以验证消息合法。

但 Bob 无法向第三方证明这条消息一定是 Alice 发的,因为 Bob 自己也有 key,也可以生成合法消息。

如果需要防抵赖,要用数字签名:

Text Only
私钥签名
公钥验证

例如:

Text Only
Ed25519
ECDSA
RSA-PSS
SM2

2. AEAD 不能自动防重放

AEAD 只能判断:

Text Only
这条消息是否被篡改;
这条消息是否来自拥有密钥的一方。

但它不能自动判断:

Text Only
这条消息是不是旧的;
这条消息是不是被重复发送了。

防重放需要应用层机制:

Text Only
递增序列号
nonce 去重
时间戳
短期挑战响应
消息 ID 黑名单/白名单

3. AEAD 对 nonce 要求很高

AEAD 通常需要:

Text Only
nonce = number used once

同一个 key 下,nonce 通常不能重复。

尤其对于 AES-GCM:

Text Only
同一 key 重复 nonce 可能导致灾难性后果。

可能影响包括:

Text Only
保密性被破坏;
认证密钥泄露;
tag 可被伪造。

推荐做法:

Text Only
使用单调递增计数器;
或使用安全随机 nonce,并控制长度与碰撞概率;
或在高风险场景使用 AES-GCM-SIV 这类 nonce-misuse resistant 算法。

4. AEAD 不解决密钥分发问题

AEAD 是对称算法,通信双方必须共享同一个 key。

因此问题变成:

Text Only
如何安全地共享 key?

常见方案:

Text Only
TLS 握手
Diffie-Hellman / ECDHE
KDF 派生密钥
密钥管理系统 KMS
预共享密钥 PSK

如果密钥泄露,AEAD 的保密性和完整性都会失效。


十三、AEAD 与普通数字签名的关系总结

可以这样理解:

Text Only
AEAD:
    我们双方共享一个秘密;
    我可以确认消息来自你,且没被改;
    但无法向第三方证明。

数字签名:
    你用私钥签名;
    任何人都可以用你的公钥验证;
    可以公开证明,且你难以抵赖。

对应关系:

能力 AEAD 数字签名
保密性 通常有 无,除非额外加密
完整性 有 有
来源认证 有,但仅限共享密钥双方 有
第三方验证 无 有
防抵赖 无 有
性能 高 相对较低
密钥类型 对称密钥 非对称密钥

十四、完整示例:Alice 给 Bob 发送安全消息

最终完整流程如下:

Text Only
前提:
    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. 处理业务。

伪代码:

Text Only
# 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)
Text Only
# 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)

十五、最终总结

完整总结如下:

Text Only
1. 如果只是防意外损坏:
   使用普通哈希,例如 SHA-256。

2. 如果要防恶意篡改,且双方共享密钥:
   使用 HMAC / MAC,例如 HMAC-SHA256。

3. 如果既要保密,又要保证完整性:
   使用 AEAD,例如 AES-GCM 或 ChaCha20-Poly1305。

4. 如果要公开验证、防抵赖:
   使用非对称数字签名,例如 Ed25519、ECDSA、RSA-PSS、SM2。

AEAD 的核心原理是:

Text Only
用对称加密保护明文内容;
用带密钥的 tag 保护密文、nonce 和关联数据;
接收方只有验证 tag 成功后才允许解密;
任何篡改都会导致 tag 校验失败。

因此:

AEAD 能同时满足保密性和完整性,是因为它把“加密”和“带密钥认证”结合成一个安全整体:加密让别人看不见,Tag 让别人改不了。