ComSec作业二:AES
1、描述AES中S-Box的生成过程
(1)按字节值的升序逐行初始化S-Box,第一行是{00},{01},…{0F};第二行是{10},{11},…{1F}等,因此,在行y列x的字节值是{yx}。
(2)把S-Box中的每个字节映射为它在有限域 G F ( 2 8 ) GF(2^8) GF(28)中的逆,其中{00}被映射为它自身{00}。
(3)把S-Box中的每个字节的8个构成位记为 ( b 7 , b 6 , b 5 , b 4 , b 3 , b 2 , b 1 , b 0 ) (b_7,b_6,b_5,b_4,b_3,b_2,b_1,b_0) (b7,b6,b5,b4,b3,b2,b1,b0)。对S-Box的每个字节的每个位做如下变换:
b i ′ = b i ⊕ b ( i + 4 ) m o d 8 ⊕ b ( i + 5 ) m o d 8 ⊕ b ( i + 6 ) m o d 8 ⊕ b ( i + 7 ) m o d 8 ⊕ c i b_i'=b_i\oplus b_{(i+4)mod8}\oplus b_{(i+5)mod8}\oplus b_{(i+6)mod8}\oplus b_{(i+7)mod8}\oplus c_i bi′=bi⊕b(i+4)mod8⊕b(i+5)mod8⊕b(i+6)mod8⊕b(i+7)mod8⊕ci
这里的 c i c_i ci是指值为{63}的字节c的第i位,即 ( c 7 c 6 c 5 c 4 c 3 c 2 c 1 c 0 ) = ( 01100011 ) (c_7 c_6 c_5 c_4 c_3 c_2 c_1 c_0)=(01100011) (c7c6c5c4c3c2c1c0)=(01100011)。用矩阵形式表示为:
[ b 0 ′ b 1 ′ b 2 ′ b 3 ′ b 4 ′ b 5 ′ b 6 ′ b 7 ′ ] = [ 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 ] [ b 0 b 1 b 2 b 3 b 4 b 5 b 6 b 7 ] + [ 1 1 0 0 0 1 1 0 ] \begin{bmatrix}b_0'\\ b_1' \\ b_2'\\b_3'\\b_4'\\b_5'\\b_6'\\b_7' \end{bmatrix}=\begin{bmatrix}1 & 0 & 0 & 0 & 1 & 1 & 1 & 1\\ 1 & 1 & 0 & 0 & 0 & 1 & 1 & 1\\ 1 & 1 & 1 & 0 & 0 & 0 & 1 & 1 \\ 1 & 1 & 1 & 1 & 0 & 0 & 0 & 1\\ 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0\\ 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0\\ 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0\\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1\end{bmatrix} \begin{bmatrix}b_0\\ b_1 \\ b_2\\b_3\\b_4\\b_5\\b_6\\b_7 \end{bmatrix}+\begin{bmatrix}1\\ 1 \\ 0\\0\\0\\1\\1\\0 \end{bmatrix} ⎣ ⎡b0′b1′b2′b3′b4′b5′b6′b7′⎦ ⎤=⎣ ⎡1111100001111100001111100001111110001111110001111110001111110001⎦ ⎤⎣ ⎡b0b1b2b3b4b5b6b7⎦ ⎤+⎣ ⎡11000110⎦ ⎤
最终S-Box为:
2、证明公式6.9与公式6.4等价。
对于 s 0 , j ′ s'_{0,j} s0,j′,在6.9中,其可以化为:
s 0 , j ′ = s 0 , j ⊕ T m p ⊕ [ 2 ⋅ ( s 0 , j ⊕ s 1 , j ) ] s'_{0,j}=s_{0,j}\oplus Tmp\oplus [2·(s_{0,j}\oplus s_{1,j})] s0,j′=s0,j⊕Tmp⊕[2⋅(s0,j⊕s1,j)]
= s 0 , j ⊕ ( s 0 , j ⊕ s 1 , j ⊕ s 2 , j ⊕ s 3 , j ) ⊕ [ 2 ⋅ ( s 0 , j ⊕ s 1 , j ) ] =s_{0,j}\oplus (s_{0,j}\oplus s_{1,j}\oplus s_{2,j}\oplus s_{3,j})\oplus [2·(s_{0,j}\oplus s_{1,j})] =s0,j⊕(s0,j⊕s1,j⊕s2,j⊕s3,j)⊕[2⋅(s0,j⊕s1,j)]
= s 1 , j ⊕ s 2 , j ⊕ s 3 , j ⊕ [ 2 ⋅ ( s 0 , j ⊕ s 1 , j ) ] =s_{1,j}\oplus s_{2,j}\oplus s_{3,j}\oplus [2·(s_{0,j}\oplus s_{1,j})] =s1,j⊕s2,j⊕s3,j⊕[2⋅(s0,j⊕s1,j)]
= ( 2 ⋅ s 0 , j ) ⊕ ( 3 ⋅ s 1 , j ) ⊕ s 2 , j ⊕ s 3 , j =(2·s_{0,j})\oplus (3·s_{1,j})\oplus s_{2,j}\oplus s_{3,j} =(2⋅s0,j)⊕(3⋅s1,j)⊕s2,j⊕s3,j
对于 s 1 , j ′ s'_{1,j} s1,j′,在6.9中,其可以化为:
s 1 , j ′ = s 1 , j ⊕ T m p ⊕ [ 2 ⋅ ( s 1 , j ⊕ s 2 , j ) ] s'_{1,j}=s_{1,j}\oplus Tmp\oplus [2·(s_{1,j}\oplus s_{2,j})] s1,j′=s1,j⊕Tmp⊕[2⋅(s1,j⊕s2,j)]
= s 1 , j ⊕ ( s 0 , j ⊕ s 1 , j ⊕ s 2 , j ⊕ s 3 , j ) ⊕ [ 2 ⋅ ( s 1 , j ⊕ s 2 , j ) ] =s_{1,j}\oplus (s_{0,j}\oplus s_{1,j}\oplus s_{2,j}\oplus s_{3,j})\oplus [2·(s_{1,j}\oplus s_{2,j})] =s1,j⊕(s0,j⊕s1,j⊕s2,j⊕s3,j)⊕[2⋅(s1,j⊕s2,j)]
= s 0 , j ⊕ s 2 , j ⊕ s 3 , j ⊕ [ 2 ⋅ ( s 1 , j ⊕ s 2 , j ) ] =s_{0,j}\oplus s_{2,j}\oplus s_{3,j}\oplus [2·(s_{1,j}\oplus s_{2,j})] =s0,j⊕s2,j⊕s3,j⊕[2⋅(s1,j⊕s2,j)]
= s 0 , j ⊕ ( 2 ⋅ s 1 , j ) ⊕ ( 3 ⋅ s 2 , j ) ⊕ s 3 , j =s_{0,j}\oplus (2·s_{1,j})\oplus (3·s_{2,j})\oplus s_{3,j} =s0,j⊕(2⋅s1,j)⊕(3⋅s2,j)⊕s3,j
对于 s 2 , j ′ s'_{2,j} s2,j′,在6.9中,其可以化为:
s 2 , j ′ = s 2 , j ⊕ T m p ⊕ [ 2 ⋅ ( s 2 , j ⊕ s 3 , j ) ] s'_{2,j}=s_{2,j}\oplus Tmp\oplus [2·(s_{2,j}\oplus s_{3,j})] s2,j′=s2,j⊕Tmp⊕[2⋅(s2,j⊕s3,j)]
= s 2 , j ⊕ ( s 0 , j ⊕ s 1 , j ⊕ s 2 , j ⊕ s 3 , j ) ⊕ [ 2 ⋅ ( s 2 , j ⊕ s 3 , j ) ] =s_{2,j}\oplus (s_{0,j}\oplus s_{1,j}\oplus s_{2,j}\oplus s_{3,j})\oplus [2·(s_{2,j}\oplus s_{3,j})] =s2,j⊕(s0,j⊕s1,j⊕s2,j⊕s3,j)⊕[2⋅(s2,j⊕s3,j)]
= s 0 , j ⊕ s 1 , j ⊕ s 3 , j ⊕ [ 2 ⋅ ( s 2 , j ⊕ s 3 , j ) ] =s_{0,j}\oplus s_{1,j}\oplus s_{3,j}\oplus [2·(s_{2,j}\oplus s_{3,j})] =s0,j⊕s1,j⊕s3,j⊕[2⋅(s2,j⊕s3,j)]
= s 0 , j ⊕ s 1 , j ⊕ ( 2 ⋅ s 2 , j ) ⊕ ( 2 ⋅ s 3 , j ) =s_{0,j}\oplus s_{1,j}\oplus (2·s_{2,j})\oplus (2·s_{3,j}) =s0,j⊕s1,j⊕(2⋅s2,j)⊕(2⋅s3,j)
对于 s 3 , j ′ s'_{3,j} s3,j′,在6.9中,其可以化为:
s 3 , j ′ = s 3 , j ⊕ T m p ⊕ [ 2 ⋅ ( s 3 , j ⊕ s 0 , j ) ] s'_{3,j}=s_{3,j}\oplus Tmp\oplus [2·(s_{3,j}\oplus s_{0,j})] s3,j′=s3,j⊕Tmp⊕[2⋅(s3,j⊕s0,j)]
= s 3 , j ⊕ ( s 0 , j ⊕ s 1 , j ⊕ s 2 , j ⊕ s 3 , j ) ⊕ [ 2 ⋅ ( s 3 , j ⊕ s 0 , j ) ] =s_{3,j}\oplus (s_{0,j}\oplus s_{1,j}\oplus s_{2,j}\oplus s_{3,j})\oplus [2·(s_{3,j}\oplus s_{0,j})] =s3,j⊕(s0,j⊕s1,j⊕s2,j⊕s3,j)⊕[2⋅(s3,j⊕s0,j)]
= s 0 , j ⊕ s 1 , j ⊕ s 2 , j ⊕ [ 2 ⋅ ( s 3 , j ⊕ s 0 , j ) ] =s_{0,j}\oplus s_{1,j}\oplus s_{2,j}\oplus [2·(s_{3,j}\oplus s_{0,j})] =s0,j⊕s1,j⊕s2,j⊕[2⋅(s3,j⊕s0,j)]
= ( 3 ⋅ s 0 , j ) ⊕ s 1 , j ⊕ s 2 , j ⊕ ( 2 ⋅ s 3 , j ) =(3·s_{0,j})\oplus s_{1,j}\oplus s_{2,j}\oplus (2·s_{3,j}) =(3⋅s0,j)⊕s1,j⊕s2,j⊕(2⋅s3,j)
由此可见,公式 6.9 与 公式 6.4 等价。
3、写一个GF(28)的乘法函数Mul,输入GF(28)的两个元素a、b,输出a * b 。提示:回忆CINTA的Simple Multiplication。
#include<iostream>
using namespace std;
unsigned char Doublenum(unsigned char x); //求x与2的乘积,实际上是左移
unsigned char Mul(unsigned char a, unsigned char b); //GF(2^8)的乘法函数
int main()
{
int a, b;
cout << "输入 a 和 b 的值" << endl;
cin>>a>>b;
cout << "a*b = ";
//最后用16进制来表示结果
printf("%#X", Mul(a, b));
cout << endl;
return 0;
}
unsigned char Doublenum(unsigned char x)
{
//判断x的最高位是否为1,若是1的话还要异或上00011011
return ((x << 1) ^ ((x & 0x80) ? 0x1b : 0x00));
}
unsigned char Mul(unsigned char a, unsigned char b)
{
unsigned char array_a[8] = { a }; //用来存储a每次左移的结果,a的2^n次
unsigned char product = 0x00;
int i = 0;
for (i = 1; i < 8; i++)
{
array_a[i] = Doublenum(array_a[i - 1]);
}
//如果b的最低位是1,则先加上a
product = (b & 0x01) * a;
//通过对b的右移,将a左移的结果加到product里,乘法的本质就是累加和
for (i = 1; i <= 7; i++)
{
product ^= (((b >> i) & 0x01) * array_a[i]);
}
return product;
}
4、写一个程序,生成AES算法中的S-Box。
#include<iostream>
#include <cstdio>
using namespace std;
unsigned char S_box[16][16];
void initialize(); //初始化 S-Box[i][j] <- {ij}
unsigned char msb(unsigned short num); //找到非零最高位并返回
unsigned char divide(unsigned short a, unsigned char b, unsigned char& r); //多项式除法,返回a/b
unsigned char Mul(unsigned char a, unsigned char b); //GF(2^8)乘法,返回a * b
unsigned char inverse(unsigned char b); //扩展欧几里得算法求b在GF(2^8)的乘法逆元
unsigned char map(unsigned char a); //映射
int main()
{
initialize();
unsigned char i, j;
for (i = 0; i <= 0xF; i++)
{
for (j = 0; j <= 0xF; j++)
{
S_box[i][j] = map(S_box[i][j]);
printf("%02X ", S_box[i][j]);
}
printf("\n");
}
return 0;
}
//扩展欧几里得算法求b在GF(2^8)的乘法逆元
void initialize()
{
unsigned char i, j;
for (i = 0; i <= 0xF; i++)
{
for (j = 0; j <= 0xF; j++)
{
S_box[i][j] = inverse((i << 4) + j); //使第i行第j列的元素为{xj}
}
}
}
//找到非零最高位并返回
unsigned char msb(unsigned short num)
{
unsigned char i;
for (i = 0; i <= 8; i++)
{
if (!(num >> (i + 1)))
{
return i;
}
}
}
//多项式除法,返回a/b
unsigned char divide(unsigned short a, unsigned char b, unsigned char& r)
{
unsigned char a_msb = msb(a);
unsigned char b_msb = msb(b);
if (a < b)
{
r = a;
return 0;
}
unsigned char bit = a_msb - b_msb;
unsigned short temp = b;
temp = temp << bit;
a = a ^ temp;
return (1 << bit) | divide(a, b, r);
}
//GF(2^8)乘法,返回a * b
unsigned char Doublenum(unsigned char x)
{
//判断x的最高位是否为1,若是1的话还要异或上00011011
return ((x << 1) ^ ((x & 0x80) ? 0x1b : 0x00));
}
unsigned char Mul(unsigned char a, unsigned char b)
{
unsigned char array_a[8] = { a }; //用来存储a每次左移的结果,a的2^n次
unsigned char product = 0x00;
int i = 0;
for (i = 1; i < 8; i++)
{
array_a[i] = Doublenum(array_a[i - 1]);
}
//如果b的最低位是1,则先加上a
product = (b & 0x01) * a;
//通过对b的右移,将a左移的结果加到product里,乘法的本质就是累加和
for (i = 1; i <= 7; i++)
{
product ^= (((b >> i) & 0x01) * array_a[i]);
}
return product;
}
//扩展欧几里得算法求b在GF(2^8)的乘法逆元
unsigned char inverse(unsigned char b)
{
if (b == 0)
return 0;
short r0 = 0x11B;
unsigned char r1 = b, r2, q;
unsigned char w0 = 0, w1 = 1, w2;
q = divide(r0, r1, r2);
w2 = w0 ^ Mul(q, w1);
while (1)
{
if (r2 == 0)
break;
r0 = r1;
r1 = r2;
q = divide(r0, r1, r2);
w0 = w1;
w1 = w2;
w2 = w0 ^ Mul(q, w1);
}
return w1;
}
//映射
unsigned char map(unsigned char a)
{
unsigned char c = 0x63;
unsigned char res = 0x0;
unsigned char temp = 0x0;
unsigned char i;
for (i = 0; i < 8; i++)
{
temp = temp ^ ((a >> i) & 0x1) ^ ((a >> ((i + 4) % 8)) & 0x1);//优先级>> 高于 &
temp = temp ^ ((a >> ((i + 5) % 8)) & 0x1) ^ ((a >> ((i + 6) % 8)) & 0x1);
temp = temp ^ ((a >> ((i + 7) % 8)) & 0x1) ^ ((c >> i) & 0x1);
res = res | (temp << i);
temp = 0x0;
}
return res;
}