AES 对称加密学习笔记

AES 对称加密学习笔记 Recommended

4月 26, 2019
Algorithms, Recommended, 密码学, 读书笔记

工作中的需求,需要一个基于 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),如下图所示。

image-20211130005104299

AES 轮函数 #

AES 的轮函数由以下几个部分组成,另外,AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。

  • SubBytes(逐字节替换)
  • ShiftRow(平移行)
  • MixColumns(混合列)
  • AddRoundKey(与轮密钥进行 XOR 运算)

SubBytes 字节替换 #

使用 S-box (S 盒)进行查找并替换。

img

ShiftRow 行移位 #

每一列都向左循环位移某个偏移量。

img

MixColumns 列混合 #

将每一列的 4 字节的值进行比特运算得到另一个 4 字节值。

img

AddRoundKey 轮密钥加 #

将 MixColumns 的输出和轮密钥进行异或运算,每个子密钥由密钥生成方案产生。

img

分组密码工作模式 #

前面提到了如果要加密的明文比较长,就需要对加密进行迭代,这种迭代模式即为分组密码工作模式(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 encryption.png

攻击方法:我们发现 ECB 模式下同样的明文可以得到同样的密文,这是由于他的结构定死的,无法改变,针对 ECB 的攻击可以想象即使不需要破解密码,只需要密文调整顺序,就可以操纵对应的明文了。

CBC #

每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量IV(Initialization Vector)。CBC 要求第一个分组的明文在加密运算前先与IV进行异或;从第二组开始,所有的明文先与前一分组加密后的密文进行异或。通常建议每次加密使用随机的 IV,这样可以保证同样的明文分组加密得到的密文是不一样的。多数情况下,同一密钥不适合多次使用同一 IV,并且 IV 需要加解密双方共同知晓。

Cbc encryption.png

攻击方法:

  1. 填充提示攻击
  2. 对初始化向量(IV)进行攻击

CFB #

CFB 在迭代模式上和 CBC 很相近,但是有两个重要区别是 CFB 可以将块密码变为自同步的流密码字典,然后用密码字典与明文进行异或操作并最终生成密文。另一个区别就是 CFB 模式是用分组算法实现流算法,所以明文数据也就不需要按分组大小对齐。即 CFB 是一种用分组密码实现流密码的方式。

Cfb encryption.png

攻击方法:重放攻击。

OFB #

OFB 模式与 CFB 模式不同的地方是:生成字典的时候会采用明文参与运算,CFB采用的是密文。和 CFB 一样也是采用流密码算法。

Ofb encryption.png

CTR #

CTR模式(Counter mode,CM)也被称为ICM模式(Integer Counter Mode,整数计数模式)和SIC模式(Segmented Integer Counter)。CTR 通过递增一个加密计数器以产生连续的密钥流,其中计数器可以是任意保证长时间不产生重复输出的函数,即保证了任意长时间均不会产生重复输出。CTR 模式的特征类似于OFB,但它允许在解密时进行随机存取。由于加密和解密过程均可以进行并行处理,CTR适合运用于多处理器的硬件上。

Ctr encryption.png

攻击方式:通过上面总结的攻击方式,我们可以发现,只要是有“多余”的输入,必然会增加风险,因为输入和输出存在着某种联系。所以针对 CTR 也可以在计数器上做文章,例如基于使用简单计数器作为输入的硬件差错攻击。

小结 #

通过上面的简单介绍,可以发现每种分组加密模式其加密强度、性能都有各自的特点,我们可以针对自己业务的场景需要进行选择。

填充模式(Padding) #

当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度,常见的填充模式有:

  • PKCS5/PKCS7 字节填充
  • ANSIX923 字节填充
  • 位填充

其他对称加密算法 #

加密解密是个很有意思的课题,我们都知道加密的算法是什么,但是只要没有密钥就仍然很难破解它。学习过程中也看到了一些其他的对称加密算法,感兴趣可以了解一下。

Camellia(块加密) #

应用有:

  • Firefox
  • FreeBSD
  • GnuPG

ChaCha20(流加密) #

应用有:

  • Chrome HTTPS
  • openssh
  • OpenBSD 随机数生成器

参考资料 #

本文共 3006 字,上次修改于 Jul 17, 2024,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» 浅谈 Django-REST-Framework 的设计与源码

» 使用 Github Pages 建立免费的静态网站

» 这个博客