一、对称加密算法
对称加密的特点是加密和解密用同一个密钥,速度快,适合加密大量数据。
1. DES(Data Encryption Standard)
原理
Feistel网络结构,64位分组,56位有效密钥(8字节密钥中每字节最后一位是奇偶校验位,实际有效56位)。16轮迭代,每轮用不同的子密钥。
输入与参数
- 密钥长度:64位(有效56位)
- 分组长度:64位(8字节)
- 输入数据:任意长度,但需要填充到分组的整数倍
- 输出数据:和原始数据长度相同(加密后)
现状
56位密钥太短,1999年就可以22小时暴力破解。现在已经不安全,新系统中不要用。
2. AES(Advanced Encryption Standard)
原理
代换-置换网络(SPN结构),非Feistel。数据以字节矩阵排列,经过字节代换、行移位、列混合、轮密钥加等操作。轮数取决于密钥长度:128位密钥10轮,192位12轮,256位14轮。
输入与参数
- 密钥长度:128位(AES-128)、192位(AES-192)、256位(AES-256)
- 分组长度:固定128位(16字节)
- 输入数据:任意长度,不足分组长度的需要填充
- 输出数据:和原始数据长度相同(加密后)
现状
AES是目前最广泛使用的对称加密算法。AES-256是当前实际应用中的安全上限,足以应对绝大多数场景。
对称加密的工作模式
你提到的CBC、ECB、GCM都是分组密码的工作模式。分组密码一次只能加密一个固定长度的分组(比如AES一个分组16字节),但实际数据可能很长,所以需要用工作模式来串联多个分组。
ECB模式(Electronic Codebook,电子密码本)
原理
每个分组独立加密,相同明文分组产生相同密文分组。
特点
- 不需要填充时是否要求:照样需要填充(当最后一段不足分组长度时)
- 可以并行计算
- 缺点:明文中的重复模式会暴露在密文中,比如加密一张位图,加密后还能看出原图的轮廓
现状
不要用。它的安全性缺陷太明显。
CBC模式(Cipher Block Chaining,密码分组链接)
原理
每个明文分组先和前一个密文分组做异或,然后再加密。第一个分组需要和一个随机初始向量(IV)异或。
加密过程
Ciphertext[i] = Encrypt(Plaintext[i] XOR Ciphertext[i-1]),其中Ciphertext[-1] = IV
特点
- 需要填充(最后一段不足分组长度时)
- IV长度必须等于分组长度(16字节)
- 不能并行加密,但可以并行解密
- 相同明文不会产生相同密文
CTR模式(Counter,计数器模式)
原理
把一个计数器值加密,然后和明文异或得到密文。计数器逐块递增。
特点
- 不需要填充(这是它最大的优点,数据可以是任意长度,按字节处理)
- 可以并行加解密
- 需要初始随机数(nonce)和计数器初始值
GCM模式(Galois/Counter Mode,伽罗瓦计数器模式)
原理
在CTR模式基础上增加了认证功能。加密时用CTR模式产生密钥流,同时用GMAC(基于伽罗瓦域的哈希)计算认证标签。
特点
- 不需要填充
- 既能加密又能做完整性验证
- 需要两个参数:IV(通常12字节)和认证标签长度(常用16字节)
- 输出比输入多一个认证标签的长度
现状
GCM是推荐模式。一次调用同时完成加密和完整性保护,比"先加密再HMAC"更简洁高效。很多现代协议(TLS 1.3、AES-GCM in IPsec)都在用。
关于填充模式
当分组加密需要处理不足一个完整分组的数据时,必须填充。以下是常用填充模式。
PKCS#5 / PKCS#7
这是最常见的填充方式。PKCS#7 适用于任意分组长度(1-255字节),PKCS#5特指8字节分组(主要用于DES)。
规则
缺几个字节就填数值为几的字节。
例如AES分组16字节,最后一段只有11字节,缺5字节,就填0x05 0x05 0x05 0x05 0x05。
特殊情况
如果数据正好是分组的整数倍,仍然要填满整整一个分组。假设AES最后一段刚好16字节,那就要再填16个0x10。这样做是为了解密时能知道从哪里截断------解密后看最后一个字节的值k,就知道最后k字节都是填充,可以安全去掉。
Zero Padding
规则
缺几个字节就填几个0x00。
问题
如果原始数据末尾本来就有0x00,解密后无法区分哪些是真实数据、哪些是填充。所以Zero Padding只在不会出现这种歧义的场景下使用。
No Padding
规则
不填充任何字节。但前提是输入数据长度必须是分组的整数倍,否则加密会出错。
适用场景
CTR、GCM这类流式模式不需要分组对齐,所以可以用No Padding。
ISO/IEC 7816-4 Padding
规则
先填一个0x80(128),后面根据需要填0x00直到满足分组长度要求。这个方案能解决Zero Padding的二义性问题,因为0x80不太可能出现在普通文本末尾。
二、非对称加密算法
非对称加密用一对密钥:公钥加密,私钥解密。速度慢,适合加密少量数据(如传输对称密钥)。
RSA
原理
基于大整数分解难题。
选择两个大质数p和q,计算n = p × q。计算φ(n) = (p-1)×(q-1)。选一个e(通常65537),算d使得e×d ≡ 1 mod φ(n)。公钥是(e, n),私钥是d。
输入与参数
- 密钥长度:通常2048位或3072位(推荐2048起步,保守选3072)
- 输入数据长度限制:加密时明文长度 ≤ 密钥长度(单位字节) - 填充开销
- 2048位密钥 = 256字节
- 用PKCS#1 v1.5填充时,最大明文长度 = 256 - 11 = 245字节
- 用OAEP填充时,最大明文长度更短
- 输出数据长度:等于密钥长度(字节数),比如2048位密钥输出256字节
填充模式
非对称加密必须有填充,否则存在数学攻击风险。
PKCS#1 v1.5 填充
结构:0x00 0x02 [非零随机字节] 0x00 [实际数据]
随机字节至少8个。解密时会检查0x00 0x02结构,如果不对就拒绝。
OAEP(Optimal Asymmetric Encryption Padding)
更安全,用哈希函数和随机数生成两个掩码,嵌入到明文两侧。能抵抗选择密文攻击。TLS 1.3和现代RSA实现都推荐OAEP。
三、快速对比表
| 算法 | 类型 | 密钥长度 | 分组长度 | 是否需填充 | 当前建议 |
|---|---|---|---|---|---|
| DES | 对称 | 56位有效 | 64位 | 是 | 禁用 |
| AES-128 | 对称 | 128位 | 128位 | 看模式 | 可用,一般场景够用 |
| AES-256 | 对称 | 256位 | 128位 | 看模式 | 推荐,高安全场景首选 |
| RSA-2048 | 非对称 | 2048位 | - | 必须 | 推荐 |
| RSA-3072 | 非对称 | 3072位 | - | 必须 | 高安全场景推荐 |
| CBC模式 | - | - | 同底层算法 | 是 | 可用(需要搭配HMAC) |
| GCM模式 | - | - | 同底层算法 | 否 | 推荐(认证加密一体) |
| CTR模式 | - | - | 同底层算法 | 否 | 可用(需要搭配HMAC) |
几个选型建议
- 要加密大量数据:选AES-256-GCM,一把梭,加密和完整性都有了
- 只想用对称加密做机密性:AES-256-CBC,但要另外加HMAC做完整性校验
- 要安全传递对称密钥:用RSA-2048(或3072)加上OAEP填充,加密那把AES的密钥
- 国密场景:用SM4(分组128位,类似AES),工作模式也可以用CBC、GCM对应的国密版本(国密算法下一篇文章介绍)
- 老系统维护遇到DES:尽快升级替换