AES加密过程

基础知识

需要先了解什么是有限域, 伽罗瓦有限域, GF(28), 否则就是看天书

AES

AES的本质: 替换, 移位, 异或, 每一步都是可逆的

ISO/IEC 18033-3, 不是免费文档.
http://www.doc88.com/p-6405051328829.html
https://tools.ietf.org/html/rfc3962

AES每次加密128 bits数据plaintext, 也就是16字节.
AES128的key为128 bits, 执行10轮加密, 记为Nr = 10
AES192的key为192 bits, 执行12轮加密 记为Nr = 12
AES256的key为256 bits, 执行14轮加密 记为Nr = 12

加密过程如下:

  1. 初始始State表, S = P

  2. S = AddRoundKey(S, W0), 这里的W0也是一个4X4的矩阵

  3. for i=1 to (Nr-1) : { //重复Nr-1次
    S = SubBytes(S)
    S = ShiftRows(S)
    S = MixColumns(S)
    S = AddRoundKey(S, Wi)
    }

  4. S = SubBytes(S)
    S = ShiftRows(S)
    C = AddRoundKey(S, WNr)
    C即为最后的密文

解释
Wi为4X4的矩阵, 为 [w(4i),w(4i+1),w(4i+2),w(4i+4)]
小写的w是单列数据, 由密钥key扩展生成, 规则见下面的章节

代码演示
https://github.com/wzjwhut/aes-encryption

以下是每一个步骤的说明

初始化State表

假设这plaintext 16个字节的数据分别为
p0, p1, p2, … p15

首先, 创建一个4x4的表s, 这个表称为State表

State表 列0 列1 列2 列3
行0 s0,0 s0,1 s0,2 s0,3
行1 s1,0 s1,1 s1,2 s1,3
行2 s2, 0 s2,1 s2,2 s2,3
行3 s3, 0 s3,1 s3,2 s3,3

使用plaintext来初始化s
按照从上往下, 从左往右的顺序填充State表

State表 列0 列1 列2 列3
行0 p0 p4 p8 p12
行1 p1 p5 p9 p13
行2 p2 p6 p10 p14
行3 p3 p7 p11 p15

替换SubBytes()

有一张称为S-box的表, 将S表中的值替换成S-box中的的值, 规则如下
假设si,j的16进制显示为mn, 其中m∈[0, f], n∈[0,f], 那么
si,j被替换成S-boxm,n
S-box https://en.wikipedia.org/wiki/Rijndael_S-box , 这个表是通过有限域的仿射变换生成的
举例, 设 si,j = 83 = 0x53, 那么使用S-box5,3 = 0xed 替换, 也就是0x53被0xed替换.
S-Box的生成规则:
首先找出GF(28)中的互为乘法逆元的元素对, 然后对这些元素执行Rijndael变形.

S-box
0 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0 63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76
1 ca 82 c9 7d fa 59 47 f0 ad d4 a2 af 9c a4 72 c0
2 b7 fd 93 26 36 3f f7 cc 34 a5 e5 f1 71 d8 31 15
3 04 c7 23 c3 18 96 05 9a 07 12 80 e2 eb 27 b2 75
4 09 83 2c 1a 1b 6e 5a a0 52 3b d6 b3 29 e3 2f 84
5 53 d1 00 ed 20 fc b1 5b 6a cb be 39 4a 4c 58 cf
6 d0 ef aa fb 43 4d 33 85 45 f9 02 7f 50 3c 9f a8
7 51 a3 40 8f 92 9d 38 f5 bc b6 da 21 10 ff f3 d2
8 cd 0c 13 ec 5f 97 44 17 c4 a7 7e 3d 64 5d 19 73
9 60 81 4f dc 22 2a 90 88 46 ee b8 14 de 5e 0b db
a e0 32 3a 0a 49 06 24 5c c2 d3 ac 62 91 95 e4 79
b e7 c8 37 6d 8d d5 4e a9 6c 56 f4 ea 65 7a ae 08
c ba 78 25 2e 1c a6 b4 c6 e8 dd 74 1f 4b bd 8b 8a
d 70 3e b5 66 48 03 f6 0e 61 35 57 b9 86 c1 1d 9e
e e1 f8 98 11 69 d9 8e 94 9b 1e 87 e9 ce 55 28 df
f 8c a1 89 0d bf e6 42 68 41 99 2d 0f b0 54 bb 16

逆替换SubBytes-1()

SubBytes-1() 是SubBytes()还原操作
上例中, 也就是0x53被0xed替换. 还原操作就是将0xed再还原成0x53, 也是使用查表法
https://en.wikipedia.org/wiki/Rijndael_S-box 上有生成好的还原表.

行移位ShiftRows()

规则
Sr, c = Sr, (c+r) mod 4 , (0<r<4, 0≤c<4)
也就是, 第1行不变换, 剩下的3行需要变化.
比如
S1, 0 = S1, 1,
S1, 1 = S1, 2,
S1, 2 = S1, 3,
S1, 3 = S1, 0,
也就是, 第2行的数据循环向左移了1个位置. 依次类推:
第3行的数据循环向左移了2个位置
第4行的数据循环向左移了3个位置

逆行移位变换ShiftRows-1()

这是移位变换的还原操作, 也就是
第2行的数据循环向右移1个位置
第3行的数据循环向右移2个位置
第4行的数据循环向右移3个位置

列混合变换MixColumns()

公式为
S0,c = ( 2 • S0,c ) ⊕ ( 3 • S1,c) ⊕ S2,c ⊕ S3,c
S1,c = S0,c ⊕ ( 2 • S1,c ) ⊕ ( 3 • S2,c) ⊕ S3,c
S2,c = S0,c ⊕ S1,c⊕ ( 2 • S2,c ) ⊕ ( 3 • S3,c)
S2,c = ( 3 • S0,c) ⊕ S1,c ⊕ S2,c⊕ ( 2 • S3,c )

其中
表示异或操作, 也可以认为是有限域GF( 28 )中的加法操作
表示有限域GF( 28 )的乘法操作. 不是整数上的乘法操作. 代码实现可参考
https://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field
https://blog.csdn.net/wzj_whut/article/details/86521447

这个操作也可以写成矩阵形式

[ S 0 , c S 1 , c S 2 , c S 3 , c ] = [ 2 3 1 1 1 2 3 1 1 1 2 3 3 1 1 2 ] [ S 0 , c S 1 , c S 2 , c S 3 , c ] \begin{bmatrix} S_{0,c}^{&#x27;} \\S_{1,c}^{&#x27;} \\S_{2,c}^{&#x27;}\\S_{3,c}^{&#x27;} \end{bmatrix} = \begin{bmatrix} 2 &amp; 3 &amp; 1 &amp; 1 \\1 &amp; 2 &amp; 3 &amp; 1 \\1 &amp; 1 &amp; 2 &amp; 3 \\3 &amp; 1 &amp; 1 &amp; 2 \end{bmatrix} \begin{bmatrix} S_{0,c}\\S_{1,c} \\S_{2,c}\\S_{3,c} \end{bmatrix}

逆列混合变换MixColumns-1()

公式为
S0,c = ( 0e • S0,c ) ⊕ ( 0b • S1,c) ⊕ (0d • S2,c ) ⊕ ( 09 • S3,c )
S0,c = ( 09 • S0,c ) ⊕ ( 0e • S1,c) ⊕ (0b • S2,c ) ⊕ ( 0d • S3,c )
S0,c = ( 0d • S0,c ) ⊕ ( 09 • S1,c) ⊕ (0e • S2,c ) ⊕ ( 0b • S3,c )
S0,c = ( 0b • S0,c ) ⊕ ( 0d • S1,c) ⊕ (09 • S2,c ) ⊕ ( 0e • S3,c )

矩阵形式(中间的矩阵是16进制表示的)
[ S 0 , c S 1 , c S 2 , c S 3 , c ] = [ e b d 9 9 e b d d 9 e b b d 9 e ] [ S 0 , c S 1 , c S 2 , c S 3 , c ] \begin{bmatrix} S_{0,c}^{&#x27;} \\S_{1,c}^{&#x27;} \\S_{2,c}^{&#x27;}\\S_{3,c}^{&#x27;} \end{bmatrix} = \begin{bmatrix} e &amp; b &amp; d &amp; 9 \\9 &amp; e &amp; b &amp; d \\d &amp; 9 &amp; e &amp; b \\b &amp; d &amp; 9 &amp; e \end{bmatrix} \begin{bmatrix} S_{0,c}\\S_{1,c} \\S_{2,c}\\S_{3,c} \end{bmatrix}

密钥扩展Key schedule

对于AES128来说, 初始key为16个字节, 第4字节记为1列, 共4列, 记Nk=4, Nr=10 (10轮操作)
(对于AES196来说, 初始key为24个字节, 共6列, 记Nk=6, Nr=12, 其它同理)
密钥扩展的意思是: 将初始密钥扩展到4*(Nr+1) -1

伪代码如下, (小写的wi 表示第i列数据, 不是矩阵):

for j = Nk to ( 4*(Nr+1) -1 )
if( j mod Nk == 0 ) then
wj = wj-Nk ⊕ SubBytes( ShiftColumn(wj-1)) ⊕ R j/Nkc
else
wj = wj-Nk ⊕ wj-1

解释:
ShiftColumn表示将这列数据循环上移1个位置.
SubBytes( ShiftColumn(wj-1)) 表示循环上移1个位置之后, 再使用S-Box执行替换操作
R j/Nkc的计算规则为GF(28)的元素同余操作
xj/Nk -1 mod ( x8+x4+x3+x+1)
可以按照以下规则进行代码编写(也可以查表)
https://en.wikipedia.org/wiki/Rijndael_key_schedule

AddRoundKey()

Wi = [w(4i), w(4i+1), w(4i+2), w(4i+3)], 0≤i≤Nr
对State表的每列, 执行以下操作
[ S 0 , c S 1 , c S 2 , c S 3 , c ] = [ S 0 , c S 1 , c S 2 , c S 3 , c ] [ w ( 4 i + c ) ] \begin{bmatrix} S_{0,c}^{&#x27;} \\S_{1,c}^{&#x27;} \\S_{2,c}^{&#x27;}\\S_{3,c}^{&#x27;} \end{bmatrix} = \begin{bmatrix} S_{0,c}\\S_{1,c} \\S_{2,c}\\S_{3,c} \end{bmatrix} ⊕ \begin{bmatrix} w_{(4*i +c)} \end{bmatrix}

Key,PlainText未对齐16字节的处理

最简单的方式, 就是补零. 如果是加密字符串, 那么就很好处理, 遇到0, 就认为是结束符.
对于二进制的数据, 需要依赖更上层的封装协议来指明padding占用的字节长度.

AES模式

https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=51031
ECB: 最简单的方式, (原文,密钥) => 密文
CBC: 先将原文与IV异或, 再加密, (原文⊕IV ,密钥) => 密文
CFB: 过程比较复杂, 自己看文档吧. 大概就是, 上个数据块的输出, 会作为下个数据块的输入.
CTR: 复杂, 自己看文档吧.

猜你喜欢

转载自blog.csdn.net/wzj_whut/article/details/86494087