对称密码

编码

计算机的操作对象是由 0 和 1 排列而成的比特序列。无论是文字、图像、声音、视频还是程序,在计算机中都是用比特序列来表示的。执行加密操作的程序,就是将表示明文的比特序列转换为表示密文的比特序列。

将现实世界中的东西映射为比特序列的操作称为编码(encoding)。例如midnight这个单词,我们可以对其中的每一个字母逐一进行编码,这种编码规则叫 ASCII。

1
2
3
4
5
6
7
8
m  ->  01101101
i -> 01101001
d -> 01100100
n -> 01101110
i -> 01101001
g -> 01100111
h -> 01101000
t -> 01110100

XOR

XOR(exclusive or)异或运算。

1个比特的XOR

1个比特的XOR运算规则如下。

1
2
3
4
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0

可以将 0 理解为偶数,1理解为奇数,就可以将 XOR 和加法运算等同起来。

由于 XOR 和加法运算很相似,因此一般用 + 和 O 组合而成的符号 ⊕ 来表示 XOR。

1
2
3
4
0 ⊕ 0 = 0
0 ⊕ 1 = 1
1 ⊕ 0 = 1
1 ⊕ 1 = 0

规律:两个相同的数进行 XOR 运算的结果一定为 0。

比特序列的 XOR

长比特序列之间的 XOR 运算只需对其中每个相对应的比特进行 XOR 运算就可以了。

由于两个相同的数进行 XOR 运算的结果一定为 0,因此如果将 A ⊕ B 的结果再与 B 进行 XOR 运算,则结果会变回 A。也就是说,两个公式中的 B 会相互抵消。

上面的计算和加密、解密的步骤非常相似。

  • 将明文 A 用密钥 B 进行加密,得到密文 A ⊕ B
  • 将密文 A ⊕ B 用密钥 B 进行解密,得到明文 A

一次性密码本

只要通过暴力破解法对密钥空间进行遍历,无论什么密文总有一天也能够被破译。一次性密码本是个例外,即便使用暴力破解法遍历整个密钥空间,一次性密码本也绝对无法被破译。

一次性密码本的加密

一次性密码本的原理是将明文与一串随机的比特序列进行 XOR 运算。

下面将明文midnight这个字符串通过 ASCII 进行编码并产生一串比特序列。

1
2
m         i         d         n         i         g         h         t
01101101 01101001 01100100 01101110 01101001 01100111 01101000 01110100

明文被编码为一串 64 比特的比特序列。

然后再来产生一个和明文长度相同的 64 比特的随机比特序列,这个序列就是 XOR 加密的密钥。

1
01101011  11111010  01001000  11011000  01100101  11010101  10101111  00011100

将明文与密钥的比特序列进行 XOR 运算,并得到一串新的比特序列,这次运算的结果就是一次性密码本的密文。

这样产生的比特序列如果要显示在计算机上,看上去就像乱码一样,因此密文通常不会被还原成字符,而是被作为二进制数据来处理。

一次性密码本的解密

解密就是加密的反向运算。也就是说,用密文和密钥进行 XOR 运算就可以得到明文。

一次性密码本是无法破译的

这里说的无法破译并不是指在现实的时间内难以破译,而是指即使拥有一种运算能力无穷大的计算机,可以在一瞬间遍历任意大小的密钥空间,也依然无法破译。

我们假设对一次性密码本的密文尝试进行暴力破解,那么总有一天我们会尝试到和加密时相同的密钥,也就能解除明文midnight,这时毋庸置疑的事实。然而,即使我们能解密出midnight这个字符串,我们也无法判断它是否是正确的明文。

这是因为在对一次性密码本尝试解密的过程中,所有的 64 比特的排列组合都会出现,这其中既会包含像aaaaaaaaabcdefgZZZZZZZZ这样的规则字符串,也会包含midnightonenightmistress等英文单词,还会包含%Ta_AjvXER#f6等看不懂的组合。由于明文中所有可能的排列组合都会出现,因此我们无法判断其中哪一个才是正确的明文。

所谓暴力破解,就是按顺序将所有的密钥都尝试一遍,并判断所得到的是不是正确的明文的方法。

在一次性密码本中,由于我们无法判断得到的是不是正确的明文,因此一次性密码本是无法破译的。

一次性密码本为什么没有被使用

密钥的配送

接收者收到了发送者发来的密文,接收者要想进行解密,就必须使用和发送者进行加密时相同的密钥,因此发送者必须将密钥也发给接收者,且该密钥的长度和密文是相等的。但这样就产生了一个矛盾:如果能有一种方法将密钥安全的发出去,那么岂不是也可以用同样的方法来安全的发送明文吗?

密钥的保存

为了保护明文,就需要保护和明文一样长的密钥。密钥不能丢弃或删除,因为没有密钥就无法解密,丢弃密钥就等于丢弃明文。也就是说,我们只是将保护明文这一命题替换成了保护和明文一样长的密钥而已,问题没有得到实质性的解决。

密钥的重用

在一次性密码本中绝对不能重用过去用过的随机比特序列,因为作为密钥的比特序列一旦泄露,过去所有的机密通信内容将全部被解密。

密钥的同步

当明文很长时,一次性密码本的密钥也会跟着变长。而且在通信过程中,发送者和接收者的密钥比特序列不允许有任何错位,否则错位的比特后的所有信息都将无法解密。

密钥的生成

在一次性密码本中,需要生成大量的随机数。这里的随机数必须是无重现性的真正随机数。出于这个原因,能够真正使用一次性密码本的,只有那些机密性重过一切,且可以花费大量财力和人力来生成并配送密钥的场合。

综上所述,一次性密码本是一种几乎没有实用价值的密码。

DES

随着计算机的进步,现在 DES 已经能够被暴力破解,因此除了用它来解密以前的密文外,不应该再使用 DES 了。

加密和解密

DES 是一种将 64 比特的明文加密成 64 比特的密文的对称密码算法,它的密钥长度是 56 比特。尽管从规格上来说,DES 的密钥长度是 64 比特,但由于每隔 7 比特会设置一个用于错误检查的比特,因此实质上其密钥长度是 56 比特。

DES 是以 64 比特的明文(比特序列)为一个单位来进行加密的,这个 64 比特的单位称为分组。一般来说,以分组为单位进行处理的密码算法称为分组密码(block cipher),DES 就是分组密码的一种。

DES 每次只能加密 64 比特的数据,如果要加密的明文比较长,就需要对 DES 加密进行迭代,而迭代的具体方式就称为模式。

DES 的结构(Feistel 网络)

DES 的基本结构是由 Horst Feistel 设计的,因此也称为 Feistel 网络、Feistel 结构。

在 Feistel 网络中,加密的各个步骤称为轮,整个加密过程就是进行若干次轮的循环。

下图是 Feistel 网络中一轮的计算流程。DES 是一种 16 轮循环的 Feistel 网络。

上图中,子密钥指的是本轮加密所使用的密钥。在 Feistel 网络中,每一轮都需要使用一个不同的子密钥。

轮函数的作用是根据右侧和子密钥生成对左侧进行加密的比特序列,它是密码系统的核心。将轮函数的输出与左侧进行 XOR 运算,其结果是加密后的左侧。也就是说,我们用 XOR 将轮函数的输出与左侧进行了合并。而输入的右侧则会直接成为输出的右侧。

一轮的具体计算步骤:

  1. 将输入的数据等分为左右两部分
  2. 将输入的右侧直接发送到输出的右侧
  3. 将输入的右侧发送到轮函数
  4. 轮函数根据右侧数据和子密钥,计算出一串看上去是随机的比特序列
  5. 将上一步得到的比特序列与左侧数据进行 XOR 运算,并将结果作为加密后的左侧

但是这样一来右侧根本没有被加密,因此我们需要用不同的子密钥对一轮的处理重复若干次,并在每两轮处理之间将左侧和右侧的数据对调。

下图展示了一个 3 轮的 Feistel 网络,3 轮加密计算需要进行两次左右对调。对调只在两轮之间进行,最后一轮结束之后不需要对调。

将一轮加密的输出结果用相同的子密钥重新运行一次,无论轮函数的具体算法是什么,都能将密文正确的还原为明文。

有多个轮的情况下也是一样。也就是说,Feistel 网络的解密操作只要按照相反的顺序来使用子密钥就可以完成了,而 Feistel 网络本身的结构,在加密和解密时都是完全相同的。

Feistel 网络的性质:

  • Feistel 网络的轮数可以任意增加。无论进行多少轮的加密计算,都不会发生无法解密的情况。
  • 加密时无论使用任何函数作为轮函数都可以正确解密。轮函数可以无需考虑解密的问题,可以被设计的任意复杂。
  • 加密和解密可以用完全相同的结构来实现,因此用于实现 DES 算法的硬件设备的设计也变容易了。

综上所述,无论是任意轮数,任何轮函数,Feistel 网络都可以用相同的结构实现加密和解密,且加密的结果必定能够正确解密。

三重 DES

现在 DES 可以被暴力破解,因此我们需要一种用来替代 DES 的分组密码,三重 DES 就是出于这个目的被开发出来的。

三重 DES 是将 DES 重复 3 次所得到的一种密码算法,缩写为 3DES。

三重 DES 的加密

下图是 3DES 的加密机制。

AES

AES(Advanced Encryption Standard) 是取代其前任标准(DES)而成为新标准的一种对称密码算法。

Rijndael

Rijndael 是由密码学家 Joan Daemen 和 Vincent Rijmen 设计的分组密码算法,于 2000 年被选为新一代的标准密码算法——AES。

Rijndael 的分组长度和密钥长度可以分别以 32 比特为单位在 128 比特到 256 比特的范围内进行选择。不过在 AES 的规格中,分组长度固定为 128 比特,密钥长度只有 128、192 和 256 比特三种。

Rijndael 的加密和解密

和 DES 一样,Rijndael 算法也是由多个轮构成的,其中每一轮分为SubBytesShiftRowsMixColumnsAddRoundKey共 4 个步骤。DES 使用 Feistel 网络作为其基本结构,而 Rijndael 没有使用 Feistel 网络,而是使用了 SPN 结构。

Rijndael 的输入分组为 128 比特,也就是 16字节。首先,需要逐个字节的对 16 字节的输入数据SubBytes处理。所谓SubBytes,就是以每个字节(0~255 的任意值)的值为索引,从一张拥有 256 个值的替换表中查找出对应值的处理。也就是说,要将一个 1 字节的值替换成另一个 1 字节的值。

SubBytes之后需要进行ShiftRows处理,这一步是将以 4 字节为单位的行按照一定的规则向左平移,且每一行平移的字节数是不同的。

ShiftRows之后需要进行MixColumns处理。这一步是对一个 4 字节的值进行比特运算,将其变为另外一个 4 字节值。

最后,需要将MixColumns的输出与轮密钥进行 XOR,即进行AddRoundKey处理。

到这里,Rijndael 的一轮就结束了。实际上,在 Rijndael 中需要重复进行 10~14轮计算。

通过上面的结构可以发现输入的所有比特在一轮中都会被加密。和每一轮都只加密一半输入的比特的 Feistel 网络相比,这种方式的优势在于加密所需要的的轮数更少。此外,SubBytes、ShifRowsMixColumns可以分别以字节、行和列为单位进行并行计算。

在 Rijndael 的加密过程中,每一轮所进行的处理为:SubBytes -> ShifRows -> MixColumns -> AddRoundKey

在解密时,则是按照相反的顺序来进行的,即AddRoundKey -> InvMixColumns -> InvShifRows -> InvSubBytes。其中,AddRoundKey是与轮密钥进行 XOR 运算,因此这一步在加密和解密时是完全相同的,剩下的步骤中名字前面都带有Inv,表示与原始步骤相对应的逆运算。

打赏
  • Copyrights © 2017-2023 WSQ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信