对称加密基础:AES算法要点归纳

讲字段级加密,绕不开AES。

它现在是全球标准。银行、云服务、物联网,都在用。

我个人习惯,只要项目没有特殊合规要求,对称加密默认选AES。为什么?因为它经过二十年公开检验,目前没有有效的攻击方式。

AES 是什么?不是新的,但很稳

AES 的前身叫 Rijndael 算法。2001年被美国NIST定为标准。

说白了,它就是一套用同一个密钥加密和解密的规则。速度快,硬件支持好。

来,看核心参数:

特性 值
数据块大小 128位(固定)
密钥长度 128、192、256位
轮数 10(128位)、12(192位)、14(256位)
支持操作模式 ECB、CBC、CTR、GCM等

注意,数据块必须是128位。密钥越长,轮数越多,越安全。我司的支付系统在PCI-DSS合规改造时,统一要求AES-256。大家记住,AES-128 当前够用,但很多监管已经强制 AES-256 了。

内部到底干了什么?

这里我用一张图说明 AES-128 的加密流程。你看,它就四个基本操作,重复十轮。

AES-128 加密流程 明文(128位) 初始轮密钥加 (AddRoundKey) 第1-9轮(每轮) 1. 字节代换(SubBytes) 2. 行移位(ShiftRows) 3. 列混合(MixColumns) 4. 轮密钥加(AddRoundKey) 最后一轮(第10轮) 1. 字节代换(SubBytes) 2. 行移位(ShiftRows) 3. 轮密钥加(AddRoundKey) (无列混合) 密文(128位) ⓘ 密钥扩展:第一轮密钥由原始密钥直接使用,后续轮密钥通过扩展算法生成。

搞懂这张图,AES就算入门了。

我一个个讲。你想想看,每次加密都要把数据切成128位的小块,然后对每个块跑十轮操作。

四个核心步骤,真正干活

1. 字节代换(SubBytes)

这一步的本质是查表。每个字节都通过S盒映射成另一个字节。S盒是设计好的非线性变换。它提供了混淆性。

嗯,S盒的实现细节我就不展开讲了。它在硬件里通常用查找表,在软件里也一样。关键是它抵抗线性攻击和差分攻击。

2. 行移位(ShiftRows)

把状态矩阵的每一行循环左移。第一行不移,第二行移1字节,第三行移2字节,第四行移3字节。

你可以想象成搬砖。每块数据在行之间交换位置。这就实现了扩散。

为什么要这么做? 如果不移位,每一列的变化影响不到其他列,加密就太弱了。

3. 列混合(MixColumns)

这步稍微数学一点。每列的四个字节,通过一个固定矩阵乘法得到新值。注意是在有限域GF(2⁸)上运算。

简单说,它让一列的四个字节互相影响。在项目中我见过有人把这个函数写错,结果密文解密后全是乱码。后来调试了一整天才发现是伽罗瓦域乘法实现有bug。

4. 轮密钥加(AddRoundKey)

把状态矩阵和轮密钥做XOR。

这一步很简单但至关重要。没它,加密就是一纸空文。密钥扩展算法保证每轮的密钥都不一样。

好,再看一眼流程图。

避坑指南: 我曾经在嵌入式项目里直接用AES原生算法加密固件包,结果发现每密文块长度和明文一样。后来一想,对了,AES是块加密,没加填充算法和认证模式。密码用对了,模式用错了,照样被攻破。

密钥扩展:不要直接用密钥硬编码

AES的总轮密钥位数 = 块大小 × (轮数+1)。

比如AES-128:128 × (10+1) = 1408位。

密钥扩展算法流程(概括版):
- 将原始密钥(16、24或32字节)放入前Nk个字。
- 每轮生成一个字(4字节):
  - 如果 i mod Nk == 0:先循环左移,再S盒代换,然后与轮常数异或。
  - AES-256还有额外的S盒操作。
- 将所有字排成阵列,用于每轮轮密钥加。

我踩过的一个坑,是大家在代码里把AES密钥直接当轮密钥用。结果呢?第一轮完了就没了。需要扩展出10轮(128位)或14轮(256位)的完整子密钥。

操作模式:你知道CBC和GCM的区别吗?

AES本身只定义块加密。实际使用时需要模式。

模式 特性 适用场景
ECB 相同明文块产生相同密文块 基本不用
CBC 需要初始化向量(IV),前后块关联 文件加密、数据库列
CTR 流式加密,可并行 高性能、网络传输
GCM AEAD,同时保证机密性和完整性 字段级加密、API令牌

我的建议是,能用GCM就别用CBC。GCM自带认证标签,可以检测篡改。你想想看,CBC模式下,如果攻击者改变了第一个块,后面所有块都变成乱码,但服务器可能误报、没有报错,数据已经损坏。GCM直接返回失败。

警告: ECB模式不要用于生产环境。我记得在PayPal的早期API里看到过ECB加密的漏洞——同一用户ID每次加密结果一样,攻击者直接通过密文比对就能知道用户重复提交。这就是EVE(类似CBC的漏洞)?不,这是ECB的先天性缺陷。

实践要点

  • 密钥管理:不要硬编码密钥到代码里。使用KMS或HSM。
  • IV要求:CBC和GCM的IV必须唯一。重复IV等于没加密。
  • 填充方式:AES是块加密,明文长度不一定是16倍。PKCS#7填充最常见。
  • 性能:AES-128比AES-256快约40%。但很多合规要求256。自已权衡。

来一组实际代码示例(Python),这是我常用来测试项目加密模块的片段:

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os

# 生成密钥和IV
key = os.urandom(32)  # AES-256
iv = os.urandom(12)   # GCM模式的nonce

# 构造加密器
cipher = Cipher(algorithms.AES(key), modes.GCM(iv))
encryptor = cipher.encryptor()

# 加密
plaintext = b"pay_password"
ciphertext = encryptor.update(plaintext) + encryptor.finalize()

# 获取认证标签
tag = encryptor.tag

# 解密
decryptor = Cipher(algorithms.AES(key), modes.GCM(iv, tag)).decryptor()
decrypted = decryptor.update(ciphertext) + decryptor.finalize()

print(decrypted)  # 输出 b"pay_password"

这段代码我经常在微服务里做字段级加密的基准测试。

注意: GCM模式下,如果密文或tag被篡改,解密会抛出异常。不要忽略这个异常——它保护你的数据完整性。

说在最后

AES不是万能药。但它是对称加密领域最成熟的选项。只要密钥管理和模式选择不出错,它足够保护你的字段级数据。

我遇到过年轻工程师问:「AES会不会过时?」短期不会。它的安全性在可预见的未来内足够抵御量子计算机以外的威胁——记住,后量子时代才考虑替代。现在,专心把AES用对。