跳转到内容

对称密码

对称密码用同一把钥匙加密与解密——快,但密钥分发与认证是它的短板(后者见哈希函数与消息认证与公钥密码)。本章讲 AES 与分组密码的工作模式、认证加密,以及"不要自己设计密码学"的原则。

分组密码把固定大小的块(128 位)在密钥控制下打乱。AES(Rijndael)是事实标准:

  • 块 128 位,密钥 128/192/256 位;
  • 内部是多轮代换-置换网络(SPN):字节代换(S 盒)、行移位、列混合、轮密钥加——混淆与扩散(Shannon 的两条原则):混淆隐藏密钥与密文的关系,扩散让明文每一位影响密文的多位。

AES 的安全性建立在两个假设上:密钥足够长(不可穷举)与没有比暴力更好的攻击(侧信道是例外,见下)。硬件指令(AES-NI)让它比软件模拟快百倍——加密不再昂贵,协议设计才是瓶颈。

分组密码只能加密一个块,模式决定如何加密任意长度:

模式做法安全性
ECB每块独立加密泄漏明文模式——不要用
CBC每块与前一块密文异或后加密需随机 IV;填充预言攻击(需小心)
CTR加密计数器流,与明文异或(流密码化)nonce 绝不能重复;可并行
GCMCTR + 认证标签(GHASH)AEAD,现代默认

ECB 模式泄漏明文模式:相同明文块 → 相同密文块——著名的企鹅图(ECB 加密的图片仍能看到企鹅轮廓)。任何场景都不要用 ECB。

  • CBC 的坑:IV 必须随机不可预测;填充预言(padding oracle)攻击——解密错误的报文差异泄漏明文(修复:恒定时间错误处理,或直接用 GCM);
  • CTR 把分组密码变成流密码:计数器加密后与明文异或——可并行、无填充,但 nonce 重复 = 密钥流重复 = 全盘皆输(见下)。

加密不等于认证:加密只保证机密性,攻击者仍可篡改密文(位翻转攻击:CBC 下翻转密文位会翻转对应明文位)——接收方解密出被篡改的内容而不自知。

认证加密(AEAD)同时保证机密性与完整性:

  • AES-GCM:CTR 加密 + GHASH 认证标签——现代默认;
  • ChaCha20-Poly1305:无硬件 AES 指令时(移动端)更快;
  • 附加认证数据(AAD):不加密但要认证的头部。

TLS 1.3 只保留 AEAD 套件——"加密且认证"是协议的底线,裸加密模式不该再出现在新代码里。

随机数的质量决定密码学的安全:

  • CSPRNG(密码学安全的伪随机发生器):/dev/urandom、getrandom()——不要用 rand()、时间戳、UUIDv1 做密钥或 nonce;
  • nonce 的规则:GCM/CTR 的 nonce 重复会完全破坏安全性(密钥流重复 → 明文异或可解):计数器式(严格不重复)或随机式(碰撞概率可忽略);
  • IV(初始向量)同理:必须随机不可预测(CBC)。

不要自己设计,用经过审计的认证加密:

  • 用库,不用裸原语:libsodium、语言的 TLS/AEAD 库;
  • 用高级 API("加密这个消息")不用低级组装("选个模式、生成个 IV")——组装是错误的高发区;
  • 密码学失败几乎都在工程细节(nonce 复用、IV 固定、时序泄漏),不在算法本身——算法选错了反而少见(AES/ChaCha 都可靠)。
  • AES 的安全 = 足够长的密钥 + 无更好攻击;AES-NI 让加密不再昂贵
  • ECB 泄漏明文模式(企鹅图),不要用;CTR 可并行但 nonce 绝不能重复
  • 加密不等于认证:位翻转攻击篡改密文;AEAD(GCM/ChaCha20-Poly1305)是现代默认
  • nonce 重复会完全破坏 GCM 的安全性;CSPRNG 是底线
  • 原则:不要自己设计,用经过审计的库与高级 API