AES 对称加密学习笔记 Recommended
4月 26, 2019
工作中的需求,需要一个基于 Django 的数据脱敏解决方案,我们的目标是要用 AES 对称加密算法,接入不能影响现有业务逻辑,数据迁移方便,失败可以回滚,最好可以开源。经过调研与开发,我最终产出了一个开源项目:luojilab/django-mirage-field,目前已经有 50+ star。本篇即为学习对称加密算法的笔记。
异或概念 #
对称加密最基础的技术就是异或运算了,简单介绍一下。
表示法(XOR) #
含义
相同为0,不同为1,表示符号:⊕
练习
- 0 ⊕ 0 = 1
- 0 ⊕ 1 = 1
- 1 ⊕ 0 = 1
- 1 ⊕ 1 = 0
最基础的加密解密原理 #
举例:
明文 0101 ,密钥 1100
加密:
0101(明文)
1100(密钥)
—xor-
1001(密文)
解密:
1001(密文)
1100(密钥)
-xor-
0101(明文)
可见,这就是明文经过一次异或运算就是密文,密文经过一次异或运算就是明文。实际的对称加密也是这样的原理,复杂的就在于不是一个简单的异或运算了。
DES 数据加密标准 #
DES(Data encryption standard, 1977)算法结构也称为费斯妥(Feistel)网络,它将64比特的明文加密成64比特的密文,密钥长度64(实际有用的是 56 )比特。DES 每次只能加密 64 比特的数据,且需要经过 16 轮循环得到加密结果,如果要加密的明文比较长,就需要对加密进行迭代,具体的迭代方式我们一般成为迭代模式(mode),关于迭代模式后面还会具体介绍。
轮(round) #
轮是加密系统的核心,参考下图,DES 算法即 Feistel 网络结构中轮的特点如下:
- 每一轮使用不同的子密钥和相同的轮函数。
- 明文分成左侧和右侧两部分。
- 轮函数将明文的“右侧”和子密钥进行计算生成随机的比特序列,然后将其与“左侧”明文做异或运算,得到左侧密文。
- 右侧明文在一轮后不变,直接和左侧密文合并,在下一轮左右两侧交换位置。
- 加密和解密可以使用相同的结构。
破解 #
随着计算机算力的提升,1970 年代发布的 DES 算法已经不再可靠,使用暴力破解法或者优化后的选择明文攻击法(Chosen Plaintext Attack, CPA)已经可以在有限时间内破解密码。现在不再建议使用 DES 加密算法,只适用于解密陈年数据。
- 1997 年需要 96 天
- 1998 年需要 56 个小时
- 1999 年需要 22 个小时
3DES(TDES) #
3DES 是为了增加 DES 的强度,将 DES 重复 3 次得到的一种密码算法,同样的,3DES 的密码长度也是 DES 密钥长度的 3 倍。
它的加密步骤为 加密 -> 解密 -> 加密
三段 DES 加密。
那么请思考:
如何使 3DES 兼容 DES 算法?
只需要将三段密码设为一样的就可以了,这样前两次的 加密 -> 解密
相当于啥也没干。
AES #
AES (Advanced Encryption Standard, 2001) 算法是为了取代 DES 而确立的一种新标准的区块加密(Block cipher)的对称加密算法(Symmetric-key algorithm),经过评选,比利时密码学家 Joan Daemen 和 Vincent Rijmen 发明的 Rijndael 加密算法最终被选定为 AES 标准,AES 算法无条件供全世界免费使用,算法完全公开。
AES 算法逐个将 128 比特(16 字节)的分组明文进行加密,密钥长度支持128、196、256。它没有使用 Feistel 网络(结构),而是使用了 SPN 结构(代换-置换网络,Substitution-permutation network),如下图所示。
AES 轮函数 #
AES 的轮函数由以下几个部分组成,另外,AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。
- SubBytes(逐字节替换)
- ShiftRow(平移行)
- MixColumns(混合列)
- AddRoundKey(与轮密钥进行 XOR 运算)
SubBytes 字节替换 #
使用 S-box (S 盒)进行查找并替换。
ShiftRow 行移位 #
每一列都向左循环位移某个偏移量。
MixColumns 列混合 #
将每一列的 4 字节的值进行比特运算得到另一个 4 字节值。
AddRoundKey 轮密钥加 #
将 MixColumns 的输出和轮密钥进行异或运算,每个子密钥由密钥生成方案产生。
分组密码工作模式 #
前面提到了如果要加密的明文比较长,就需要对加密进行迭代,这种迭代模式即为分组密码工作模式(Block cipher mode of operation),现在着重介绍下迭代模式,1981年,DES 算法发布之后,已经公布的迭代模式有以下几种:
- ECB(电子密码本 Electronic codebook)
- CBC(密码分组链接:Cipher Block Chaining Mode)
- CFB(密文反馈:Cipher Feedback Mode)
- OFB(输出反馈:Output Feedback Mode)
2001年又针对 AES 加入了新的工作模式:
- CTR(计数器模式:Counter Mode)
ECB #
最简单的加密模式,需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。此模式的问题是无法隐藏原明文数据的模式,因为同样的明文分组加密得到的密文也是一样的。
攻击方法:我们发现 ECB 模式下同样的明文可以得到同样的密文,这是由于他的结构定死的,无法改变,针对 ECB 的攻击可以想象即使不需要破解密码,只需要密文调整顺序,就可以操纵对应的明文了。
CBC #
每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量IV(Initialization Vector)。CBC 要求第一个分组的明文在加密运算前先与IV进行异或;从第二组开始,所有的明文先与前一分组加密后的密文进行异或。通常建议每次加密使用随机的 IV,这样可以保证同样的明文分组加密得到的密文是不一样的。多数情况下,同一密钥不适合多次使用同一 IV,并且 IV 需要加解密双方共同知晓。
攻击方法:
- 填充提示攻击
- 对初始化向量(IV)进行攻击
CFB #
CFB 在迭代模式上和 CBC 很相近,但是有两个重要区别是 CFB 可以将块密码变为自同步的流密码字典,然后用密码字典与明文进行异或操作并最终生成密文。另一个区别就是 CFB 模式是用分组算法实现流算法,所以明文数据也就不需要按分组大小对齐。即 CFB 是一种用分组密码实现流密码的方式。
攻击方法:重放攻击。
OFB #
OFB 模式与 CFB 模式不同的地方是:生成字典的时候会采用明文参与运算,CFB采用的是密文。和 CFB 一样也是采用流密码算法。
CTR #
CTR模式(Counter mode,CM)也被称为ICM模式(Integer Counter Mode,整数计数模式)和SIC模式(Segmented Integer Counter)。CTR 通过递增一个加密计数器以产生连续的密钥流,其中计数器可以是任意保证长时间不产生重复输出的函数,即保证了任意长时间均不会产生重复输出。CTR 模式的特征类似于OFB,但它允许在解密时进行随机存取。由于加密和解密过程均可以进行并行处理,CTR适合运用于多处理器的硬件上。
攻击方式:通过上面总结的攻击方式,我们可以发现,只要是有“多余”的输入,必然会增加风险,因为输入和输出存在着某种联系。所以针对 CTR 也可以在计数器上做文章,例如基于使用简单计数器作为输入的硬件差错攻击。
小结 #
通过上面的简单介绍,可以发现每种分组加密模式其加密强度、性能都有各自的特点,我们可以针对自己业务的场景需要进行选择。
填充模式(Padding) #
当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度,常见的填充模式有:
- PKCS5/PKCS7 字节填充
- ANSIX923 字节填充
- 位填充
其他对称加密算法 #
加密解密是个很有意思的课题,我们都知道加密的算法是什么,但是只要没有密钥就仍然很难破解它。学习过程中也看到了一些其他的对称加密算法,感兴趣可以了解一下。
Camellia(块加密) #
应用有:
- Firefox
- FreeBSD
- GnuPG
ChaCha20(流加密) #
应用有:
- Chrome HTTPS
- openssh
- OpenBSD 随机数生成器