计算机安全学作业2
一、描述AES中S-box的生成
-
按照字节值的升序逐行初始化S盒,第一行是{00},{01},{02}…{0F};第二行是{10},{11}…{1F},所以第x行y列的字节值是{xy}。
-
将S盒子中的每一个字节映射为他在有限域GF(2^8)中的逆,{00}映射为自身。
-
把S盒子的每一个字节的8位记为(b7,b6,b5,b4,b3,b2,b1,b0),对S盒子每一个字节的每一位做如下变换:
其中,ci为字节63的第i位,即(c7c6c5c4c3c2c1c0)=(01100011)。
在有限域GF(28)中,不可约多项式为
a
(
x
)
=
x
8
+
x
4
+
x
3
+
x
+
1
a(x)=x^8+x^4+x^3+x+1
a(x)=x8+x4+x3+x+1,假设我们要求
b
(
x
)
b(x)
b(x)的逆,使用扩展欧几里得算法可以得到
a
(
x
)
v
(
x
)
+
v
(
x
)
w
(
x
)
=
d
(
x
)
a(x)v(x)+v(x)w(x)=d(x)
a(x)v(x)+v(x)w(x)=d(x)
其中, d ( x ) d(x) d(x)为1, w ( x ) w(x) w(x)是 b ( x ) b(x) b(x)模 a ( x ) a(x) a(x)的乘法逆。
我们以{83}为例,首先求16进制数{83}在有限域GF(28)上的逆元。
计算过程如下:
i | r | q | v | w |
---|---|---|---|---|
-1 | {1 0001 1011} | 1 | 0 | |
0 | {1000 0011} | 0 | 1 | |
1 | {0001 1101} | {0000 0010} | {0000 0001} | {0000 0010} |
2 | {0000 0010} | {0000 1101} | {0000 1101} | {0001 1011} |
3 | {0000 0001} | {0000 1110} | {0100 0111} | {1000 0000} |
4 | {0000 0000} | {0000 0010} | {1000 0011} | {1 0001 1011} |
5 | {0000 0001} | {1000 0000} |
得到{83}的 乘法逆元为{80},即(x7+x+1)(x7)=1(mod(x8+x4+x3+x+1))
再对16进制数{80}做变换,操作如下:
B={80}={1000 0000}
C={63}={0110 0011}
B’=b’7b’6b’5b’4b’3b’2b’1b’0
根据上面的公式定义:
b ′ 0 = b 0 ⊕ b 4 ⊕ b 5 ⊕ b 6 ⊕ b 7 ⊕ c 0 = 0 b'0=b0\oplus b4\oplus b5\oplus b6 \oplus b7 \oplus c0=0 b′0=b0⊕b4⊕b5⊕b6⊕b7⊕c0=0
b ′ 1 = b 1 ⊕ b 5 ⊕ b 6 ⊕ b 7 ⊕ b 8 ⊕ c 1 = 0 b'1=b1\oplus b5\oplus b6\oplus b7 \oplus b8 \oplus c1=0 b′1=b1⊕b5⊕b6⊕b7⊕b8⊕c1=0
b ′ 2 = b 2 ⊕ b 6 ⊕ b 7 ⊕ b 0 ⊕ b 7 ⊕ c 2 = 1 b'2=b2\oplus b6\oplus b7\oplus b0 \oplus b7 \oplus c2=1 b′2=b2⊕b6⊕b7⊕b0⊕b7⊕c2=1
b ′ 3 = b 3 ⊕ b 7 ⊕ b 0 ⊕ b 1 ⊕ b 2 ⊕ c 3 = 1 b'3=b3\oplus b7\oplus b0\oplus b1 \oplus b2 \oplus c3=1 b′3=b3⊕b7⊕b0⊕b1⊕b2⊕c3=1
b ′ 4 = b 4 ⊕ b 0 ⊕ b 1 ⊕ b 2 ⊕ b 3 ⊕ c 4 = 0 b'4=b4\oplus b0\oplus b1\oplus b2 \oplus b3 \oplus c4=0 b′4=b4⊕b0⊕b1⊕b2⊕b3⊕c4=0
b ′ 5 = b 5 ⊕ b 4 ⊕ b 5 ⊕ b 6 ⊕ b 7 ⊕ c 5 = 1 b'5=b5\oplus b4\oplus b5\oplus b6 \oplus b7 \oplus c5=1 b′5=b5⊕b4⊕b5⊕b6⊕b7⊕c5=1
b ′ 6 = b 6 ⊕ b 2 ⊕ b 3 ⊕ b 4 ⊕ b 5 ⊕ c 6 = 1 b'6=b6\oplus b2\oplus b3\oplus b4 \oplus b5 \oplus c6=1 b′6=b6⊕b2⊕b3⊕b4⊕b5⊕c6=1
b ′ 7 = b 7 ⊕ b 3 ⊕ b 4 ⊕ b 5 ⊕ b 6 ⊕ c 7 = 1 b'7=b7\oplus b3\oplus b4\oplus b5 \oplus b6 \oplus c7=1 b′7=b7⊕b3⊕b4⊕b5⊕b6⊕c7=1
所以B‘=1110 1100={EC},在S盒子中第8行,第3列对应值为{EC}。
求逆元的方法二
可以用生成元g的幂表示有限域GF(28)内的元素,某个元素可以表示为gk。因为元素是有限的,有255个,因此可以构造一个正表,对于k属于[0,254],可以求出每一个k对应的值。同时可以构造一个反表,通过多项式值gk,求k值。
对于逆元表,若a和b互为逆元,则有ab = e。用生成元表示为:g^n g^m = e = 1。又因为e = g^0 = g255。所以g^k * g(255-k) = g^(k + 255 -k) = e。于是g^k 和 g^(255-k)互为逆元。对于多项式值val,求其逆元。可以先求val对应的g幂次是多少,即g的多少次方等于val,可以通过反向表查询, 设为k。那么其逆元的幂次为255-k。此时再通过正向表查询即可。
二、证明公式6.9和公式6.4等价
解:
s
0
,
j
′
=
s
0
,
j
⊕
s
0
,
j
⊕
s
1
,
j
⊕
s
2
,
j
⊕
s
3
,
j
⊕
[
2
⋅
(
s
0
,
j
⊕
s
1
,
j
)
]
=
s
1
,
j
⊕
s
2
,
j
⊕
s
3
,
j
⊕
(
2
⋅
s
0
,
j
)
⊕
(
2
⋅
s
1
,
j
)
=
(
2
⋅
s
0
,
j
)
⊕
(
3
⋅
s
1
,
j
)
⊕
s
2
,
j
⊕
s
3
,
j
s^{'}_{0,j}=s_{0,j}\oplus s_{0,j} \oplus s_{1,j} \oplus s_{2,j} \oplus s_{3,j} \oplus [2 \cdot(s_{0,j} \oplus s_{1,j})]=\\s_{1,j} \oplus s_{2,j} \oplus s_{3,j} \oplus(2\cdot s_{0,j})\oplus(2\cdot s_{1,j})=\\(2\cdot s_{0,j})\oplus(3\cdot s_{1,j}) \oplus s_{2,j} \oplus s_{3,j}
s0,j′=s0,j⊕s0,j⊕s1,j⊕s2,j⊕s3,j⊕[2⋅(s0,j⊕s1,j)]=s1,j⊕s2,j⊕s3,j⊕(2⋅s0,j)⊕(2⋅s1,j)=(2⋅s0,j)⊕(3⋅s1,j)⊕s2,j⊕s3,j
同理可得其他三项,所以6.4和6.9等价
三、写一个GF(2^8)的乘法函数Mul
#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include <stdlib.h>
#include<string>
using namespace std;
#define ll long long
#define speed ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
vector<int> v;
int table[256];
int arcTable[256];
int invTable[256];
/*可以用生成元g的幂表示有限域GF(2^8)内的元素,某个元素可以表示为g^k。因为元素是有限的,有255个,
因此可以构造一个正表,
对于k属于[0,254],可以求出每一个k对应的值。同时可以构造一个反表,通过多项式值gk,求k值。*/
void getTable(){//由指数求结果
table[0] = 1;//g^0
for(int i = 1; i < 255; ++i)//生成元为x + 1
{
table[i] = (table[i-1] << 1 );//table[i-1]*x
if( table[i] & 0x100 )
{
table[i] ^= 0x11B;//左移一位,如果b7=1,则异或
}
table[i] ^= table[i-1];
}
}
void getArcTable(){//由结果求指数
for(int i = 0; i < 255; ++i)
arcTable[ table[i] ] = i;//下标是g^n,内容是n
}
void getInvTable(){//求逆元
//g^m * g^n = e = g^255,所以g^k和g^(255-k)互为逆元
for(int i = 0; i < 255; ++i){
int k;
k = arcTable[i];
k = 255 - k;
k %= 255;//table的取值范围为 [0, 254]
invTable[i] = table[k];
}
}
int mul(int x, int y)//乘法查表
{
if( !x || !y )
return 0;
return table[ (arcTable[x] + arcTable[y]) % 255];
}
int trans2oct(string str){//转十进制
int n = str.size();
int delta = 8-n;
if(delta<0)return -1;
if(delta!=0){
for (int i=1;i<=delta;++i){
str="0"+str;
}
}
int ans =0;
for(int i=n-1;i>=0;--i){
int t = int(str[i])-48;
//cout<<pow(2,7-i)<<" "<<t<<endl;
ans+=t*pow(2,7-i);
}
//cout<<ans<<endl;
return ans;
}
string trans2bin(int x){//转二进制
//cout<<x<<endl;
int a[10]={1,2,4,8,16,32,64,128};
string str="";
for(int i=7;i>=0;--i){
if(x-a[i]>=0){
str+="1";
x-=a[i];
}
else str+="0";
}
return str;
}
int main(){
speed;
getTable();
getArcTable();
getInvTable();
string a,b;
cout<<"输入两个二进制数"<<endl;
//cin>>a>>b;
//cout<<trans2bin(mul(trans2oct(a),trans2oct(b)));
cout<<trans2bin(invTable[trans2oct("10110010")]);
return 0;
}
四、写一个程序,生成AES算法中的S-Box
#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include <stdlib.h>
#include<string>
using namespace std;
#define ll long long
#define speed ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
vector<int> v;
int table[256];
int arcTable[256];
int invTable[256];
void getTable(){//由指数求结果
table[0] = 1;//g^0
for(int i = 1; i < 255; ++i)//生成元为x + 1
{
table[i] = (table[i-1] << 1 );//table[i-1]*x
if( table[i] & 0x100 )
{
table[i] ^= 0x11B;//左移一位,如果b7=1,则异或
}
table[i] ^= table[i-1];
}
}
void getArcTable(){//由结果求指数
for(int i = 0; i < 255; ++i)
arcTable[ table[i] ] = i;//下标是g^n,内容是n
}
void getInvTable(){//求逆元
//g^m * g^n = e = g^255,所以g^k和g^(255-k)互为逆元
for(int i = 0; i < 255; ++i){
int k;
k = arcTable[i];
k = 255 - k;
k %= 255;//table的取值范围为 [0, 254]
invTable[i] = table[k];
}
}
int mul(int x, int y)//乘法查表
{
if( !x || !y )
return 0;
return table[ (arcTable[x] + arcTable[y]) % 255];
}
int trans2oct(string str){//转十进制
int n = str.size();
int delta = 8-n;
if(delta<0)return -1;
if(delta!=0){
for (int i=1;i<=delta;++i){
str="0"+str;
}
}
int ans =0;
for(int i=7;i>=0;--i){
int t = int(str[i])-48;
//cout<<pow(2,7-i)<<" "<<t<<endl;
ans+=t*pow(2,7-i);
}
//cout<<ans<<endl;
return ans;
}
string trans2bin(int x){//转二进制
//cout<<x<<endl;
int a[10]={1,2,4,8,16,32,64,128};
string str="";
for(int i=7;i>=0;--i){
if(x-a[i]>=0){
str+="1";
x-=a[i];
}
else str+="0";
}
return str;
}
string fx(string str){
string c63 = "01100011";
int n,a[10],c[10];
n = str.size();
string ans="";
for(int i=n-1;i>=0;--i){
c[7-i]=int(c63[i])-48;
}
for(int i=n-1;i>=0;--i){
a[7-i]=int(str[i])-48;
//cout<<"a:"<<a[7-i]<<endl;
}
for(int i=n-1;i>=0;--i){//仿射变换
int b = a[7-i];
int btmp,j;
j = 7-i;
btmp = b ^ a[(j+4)%8] ^ a[(j+5)%8] ^ a[(j+6)%8] ^ a[(j+7)%8] ^ c[j];
ans=to_string(btmp)+ans;
}
//cout<<"fx:"<<ans<<endl;
return ans;
}
string hex2bin(string str){
string ans="",fans="";
for(int i=0;i<=1;++i){
if(str[i]=='A')
ans = trans2bin(10);
else if(str[i]=='B')
ans = trans2bin(11);
else if(str[i]=='C')
ans = trans2bin(12);
else if(str[i]=='D')
ans = trans2bin(13);
else if(str[i]=='E')
ans = trans2bin(14);
else if(str[i]=='F')
ans = trans2bin(15);
else ans = trans2bin(int(str[i])-48);
ans = ans.substr(4,4);
fans=fans+ans;
}
//cout<<fans<<endl;
return fans;
}
string mapp(int x){
if(x==10)return "A";
if(x==11)return "B";
if(x==12)return "C";
if(x==13)return "D";
if(x==14)return "E";
if(x==15)return "F";
return to_string(x);
}
string bin2hex(string str){
//cout<<str<<endl;
string ans="";
int a,b;
a = trans2oct(str.substr(0,4));
//cout<<a<<endl;
b = trans2oct(str.substr(4,4));
//cout<<b<<endl;
ans = mapp(a)+mapp(b);
return ans;
}
int main(){
speed;
getTable();
getArcTable();
getInvTable();
string a,b;
string word[20]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
for(int i=0;i<=15;++i){
for(int j=0;j<=15;++j){
a=word[i]+word[j];
if(i==0&&j==0)cout<<"00 ";
else cout<<bin2hex(fx(trans2bin(invTable[trans2oct(hex2bin(a))])))<<" ";
}
cout<<endl;
}
//cout<<bin2hex(fx(trans2bin(invTable[trans2oct(hex2bin("83"))])));
return 0;
}