AES加密算法
这里呢,实际上是一个标题党,本文不会带着大家手算完整的AES,而是带着大家手算一个简化版的AES,为了后文我打字方便,下面对于这个简化的AES就称之为S-AES。对于S-AES的整个过程,我主要是参考了密码学与网络安全—原理与实践这本书。
之前在讲AES的时候,已经说过S-AES了,再次看这个例子,真的越看越喜欢,因此呢,这里带着大家手算一下完整的S-AES。
前置知识
这里,我们先来回顾一下小学二年学过的加减乘除的运算,相信各位读者一定在小学二年级的时候被下面这个表支配过,我们来看一下当时我们是如何进行乘法运算的。
× | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
2 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 |
3 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 |
4 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 26 |
5 | 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 |
6 | 6 | 12 | 18 | 24 | 30 | 36 | 42 | 48 | 54 |
7 | 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 |
8 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 |
9 | 9 | 18 | 27 | 36 | 45 | 54 | 63 | 72 | 81 |
举一个小的例子,比如我们当时打算要计算 的值,那么我们可以先找到5所在的行,然后找到6所在的列,我们就可以得到 的最终结果。
好了,现在我们已经回顾了我们在小学二年级学过的乘法查表的运算,现在我们来看一下在我们今天要手算的S-AES的过程当中所用到的运算,这个也是可以通过查表来实现,和上面我们用到的九九乘法表类似,我们也是通过找到对应的行和对应的列就能找到运算之后所对应的值,下面是具体的加法表和乘法表:
加法表
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
1 | 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 | 9 | 8 | 11 | 10 | 13 | 12 | 15 | 14 |
2 | 2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 | 10 | 11 | 8 | 9 | 14 | 15 | 12 | 13 |
3 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 11 | 10 | 9 | 8 | 15 | 14 | 13 | 12 |
4 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | 12 | 13 | 14 | 15 | 8 | 9 | 10 | 11 |
5 | 5 | 4 | 7 | 6 | 1 | 0 | 3 | 2 | 13 | 12 | 15 | 14 | 9 | 8 | 11 | 10 |
6 | 6 | 7 | 4 | 5 | 2 | 3 | 0 | 1 | 14 | 15 | 12 | 13 | 10 | 11 | 8 | 9 |
7 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
8 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
9 | 9 | 8 | 11 | 10 | 13 | 12 | 15 | 14 | 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
10 | 10 | 11 | 8 | 9 | 14 | 15 | 12 | 13 | 2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 |
11 | 11 | 10 | 9 | 8 | 15 | 14 | 13 | 12 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
12 | 12 | 13 | 14 | 15 | 8 | 9 | 10 | 11 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 |
13 | 13 | 12 | 15 | 14 | 9 | 8 | 11 | 10 | 5 | 4 | 7 | 6 | 1 | 0 | 3 | 2 |
14 | 14 | 15 | 12 | 13 | 10 | 11 | 8 | 9 | 6 | 7 | 4 | 5 | 2 | 3 | 0 | 1 |
15 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
乘法表
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
2 | 0 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 3 | 1 | 7 | 5 | 11 | 9 | 15 | 13 |
3 | 0 | 3 | 6 | 5 | 12 | 15 | 10 | 9 | 11 | 8 | 13 | 14 | 7 | 4 | 1 | 2 |
4 | 0 | 4 | 8 | 12 | 3 | 7 | 11 | 15 | 6 | 2 | 14 | 10 | 5 | 1 | 13 | 9 |
5 | 0 | 5 | 10 | 15 | 7 | 2 | 13 | 8 | 14 | 11 | 4 | 1 | 9 | 12 | 3 | 6 |
6 | 0 | 6 | 12 | 10 | 11 | 13 | 7 | 1 | 5 | 3 | 9 | 15 | 14 | 8 | 2 | 4 |
7 | 0 | 7 | 14 | 9 | 15 | 8 | 1 | 6 | 13 | 10 | 3 | 4 | 2 | 5 | 12 | 11 |
8 | 0 | 8 | 3 | 11 | 6 | 14 | 5 | 13 | 12 | 4 | 15 | 7 | 10 | 2 | 9 | 1 |
9 | 0 | 9 | 1 | 8 | 2 | 11 | 3 | 10 | 4 | 13 | 5 | 12 | 6 | 15 | 7 | 14 |
10 | 0 | 10 | 7 | 13 | 14 | 4 | 9 | 3 | 15 | 5 | 8 | 2 | 1 | 11 | 6 | 12 |
11 | 0 | 11 | 5 | 14 | 10 | 1 | 15 | 4 | 7 | 12 | 2 | 9 | 13 | 6 | 8 | 3 |
12 | 0 | 12 | 11 | 7 | 5 | 9 | 14 | 2 | 10 | 6 | 1 | 13 | 15 | 3 | 4 | 8 |
13 | 0 | 13 | 9 | 4 | 1 | 12 | 8 | 5 | 2 | 15 | 11 | 6 | 3 | 14 | 10 | 7 |
14 | 0 | 14 | 15 | 1 | 13 | 3 | 2 | 12 | 9 | 7 | 6 | 8 | 4 | 10 | 11 | 5 |
15 | 0 | 15 | 13 | 2 | 9 | 6 | 4 | 11 | 1 | 14 | 12 | 3 | 8 | 7 | 5 | 10 |
后文不做特殊说明,所采用的加法和乘法运算都通过上面这两张表来实现,至于这个表是怎么来的,感兴趣的读者可以去看一下我之前讲过的有限域的相关知识,这实际上是GF(16)上面的加法和乘法运算,这里就不再过多的讨论这个表具体是怎么来的了。
手算准备
在手算之前,我们先来看一下有关S-AES当中用到的一些常量表以及回顾一下相关的函数。
S盒的生成
因为我们这次打算手算S-AES的全过程吗,因此呢,对于这个S盒怎么来的,咱们也来手算一下,当然,我用笔算是不可能的(才不是因为我笔算的准确率太低了,手动狗头),肯定是要依靠 「计算器」 的,如果有笔算上瘾的读者,可以自行的笔算一下这一些值,具体的S盒构建过程如下。
- 生成初始化状态的S盒,具体如下图所示
这个初始化状态的生成也非常简单,就是从0开始按照行往下增长,每4个一行。
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
- 将初始S盒当中的每个元素都看做GF()上面的元素,其中每个元素都可以看做是一个三阶多项式
- 对于上面的每个多项式求逆运算,得到新的S盒,其中0的映射还是0(0是没有逆元的),如下图所示
0 | 1 | 9 | 14 |
13 | 11 | 7 | 6 |
15 | 2 | 12 | 5 |
10 | 4 | 3 | 8 |
- 然后对上面求逆之后的S盒当中的元素进行如下的矩阵
这里每个元素实际上都是在GF(2)上面的哦。可能大家对这个看起来比较陌生,所以呢,我们来实际的去算一下,这里我只挑一个元素来演示了,比如说我们计算一下9这个元素对应S盒最终的值。
首先呢,先把9转换成为为二进制也就是1001
然后呢,对于带入到上面的矩阵结果就是
然后其余的元素依葫芦画瓢,我们可以得到最终的S盒
9 | 4 | 10 | 11 |
13 | 1 | 8 | 5 |
6 | 2 | 0 | 3 |
12 | 14 | 15 | 7 |
这里,我们就完成了对于S盒的生成,下面我们来看一下逆S盒是怎么来的。
逆S盒的生成
这个和生成S盒的过程类似,只不过我们需要来一次对于S盒的逆操作
- 生成初始化状态的逆S盒,具体如下图所示
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
- 对初始化之后的逆S盒做矩阵的逆变换,也就是
这里就不给一个具体的例子了,具体的矩阵运算参考S盒的运算方式,都是类似的,希望读者可以自己去算一下,这里直接给出运算后的结果。
12 | 11 | 2 | 5 |
1 | 6 | 15 | 8 |
7 | 0 | 9 | 14 |
10 | 13 | 4 | 3 |
- 然后对上面生成的S盒求GF(16)的逆运算,得到最终的逆S盒
10 | 5 | 9 | 11 |
1 | 7 | 8 | 15 |
6 | 0 | 2 | 3 |
12 | 4 | 13 | 14 |
RCON生成算法
RCON是一个轮常数,具体计算过程如下:
说人话就是一直乘以2,当然这个乘2是根据上面所说的表当中的乘法运算哦。然后 ,然后RC[i]作为RCON的左半个字节,然后右边半个字节填充0,实际效果就是左移四位,因此我们得到最终RCON的计算方法,RCON(1) = 64 = 0x80,RCON(2) = 48 = 0x30。因为简化版的AES只用到了这俩,因此算出来这俩就够了。
轮密钥加
这个操作是将16位状态矩阵和16位对应的轮密钥进行按位异或运算,这个之前的文章也讲过,可能读者也懒得去翻我之前写的,这里在来说一下吧,这个为什么叫做轮密钥加呢,实际上异或运算就是在GF(2)上的加法运算,对没有错,就是小学二年级学过的加法运算哦。因为这个加法的逆运算还是它,所以说解密的函数也是他。
半字节替代
半字节替代实际上是一个查表的操作,也就是我们上面所提到的S盒。对于状态矩阵当中的每一个元素,按照如下的方式映射为一个新的半个字节: 半字节的左边2位作为行值,右边2位作为列值。行值和列值作为索引在S和当中查找出输出。
列混淆
列混淆这块有些复杂,如果能够理解上面的S盒是怎么生成的,理解这个其实也就不难了,对于列混淆来说,实际上是对于每一列进行某个单独的操作,然后每一列都被映射成为一个新的值,具体的运算过程如下所示:
这里实际上是一个在GF(16)上面的矩阵运算,有关这个运算的规则,直接去看上面的乘法表,读者自行回顾一下小学二年级学过的九九乘法表的使用方法,然后查表去做这个新的乘法就好了,矩阵展开之后运算过程如下:
行移位
对于简化版的AES的行移位实际上非常简单,大白话就是交换一下状态矩阵第二行当中的两个半个字节。
算法过程
好了,经过上面的准备,我们可以正式来开始手算S-AES了,我们先来看一下密钥扩展算法。
密钥扩展
对于S-AES的密钥扩展,16位的初始密钥被分为两个8位,然后按照下面的方式进行计算
上文已经给出了RCON的计算方法,这里就不在赘述了,直接拿来用。
手算过程
这里我们来正式的手算一遍简化版的AES,因为分组的连接模式和算法无关,因此这里只计算一个分块,并且不考虑初始向量,说人话就是ECB模式(案例选择参考资料1)。
初始值
- 明文:
1101 0111 0010 1000
=d728
- 密钥:
0100 1010 1111 0101
=4af5
密钥扩展
对于密钥扩展来说,为了更好显示每个的运算过程,这里采用二进制进行表示了,对于密钥的初始化状态如下所示:
下面我们接着来算一下后面密钥扩展的值。
最终,我们得到了加密所需要的轮密钥。
加密过程
到现在,前期工作就完成了,我们来开始正式的加密过程。
0x01轮密钥加
提示一下,这里我采用列矩阵进行排列的,具体的加法运算采用上面的查表操作,这里就不带着大家进行手动查表了,读者大佬们自己查一下就好了。
0x02 第一轮
- 半字节替代
这里,我们来具体演示一下,一个元素的操作吧,剩余的就不每个都演示了,就用9
这个来当做例子吧,首先转换为二进制1001
然后i = 10
,j = 01
根据上面的S盒找到对应的数字就是2
。完整的结果如下所示:
- 行移位
对于行移位,就是交换第二行的两个元素,虽然对于我这个例子,是移了一个寂寞,因为第二行俩元素是一样的。
- 列混淆
列混淆就是一个普通矩阵的运算,还是计算一个元素的值当做例子吧,剩下的读者自己手动算一下,直接给出完整结果了。
来看一下第一个元素的值,具体就是矩阵的乘法,
- 轮密钥加
0x03 最后一轮
- 半字节替代
- 行移位
- 轮密钥加
到这里,整个加密过程就结束了,我们输出最后的状态矩阵,得到最终的密文0010 0100 1110 1100
。
解密过程
上面带着大家手算了加密的整个过程,这里对于解密来说,那就比较简单了,对着上面的过程来一次逆过程,这就好了,这里读者可以先自己尝试一下计算,然后再来看我计算的过程,这里不分每一轮了,简单的写一下每一步的运算过程了。
0x01 轮密钥加
0x02 逆行移位
这里实际上和行移位是一样的,但是注意,完整版的AES不一样哦。
0x03 逆半字节替代
0x04 轮密钥加
0x05 逆列混淆
0x06 逆行移位
0x07 逆半字节替代
0x08 轮密钥加
好了,到这里我们又回到了原始的明文1101 0111 0010 1000
。到这里,整个简化版的AES的加密和解密过程就都带着大家手算完成了,手动敲了这么多矩阵公式,可真累。
总结
本文带着大家手动计算了一下完整的简化版AES的整个流程,其实主要都参考了密码学与网络安全这本书,大部分的公式都是从这本书上来的,我是真的喜欢这个例子,麻雀虽小,五脏俱全,用来学习AES的入门感觉非常的合适,如果能够完整的自己手算下来这个例子,然后再去看完整版的AES算法,会简单非常多,主要就是规模扩大了一下,核心的流程还是上面这一套。最后,感谢能看到这里的读者,如果本文对大佬们理解AES有一点点的帮助,也不枉我手动敲了这么多的公式和矩阵了。