目录
三、写一个GF(2^8)的乘法函数Mul,输入GF(2^8)的两个元素a、b,输出a * b 。提示:回忆CINTA的Simple Multiplication。
一、描述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)。
可以用生成元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等价。
公式6.9:
公式6.4
证明:
三、写一个GF(2^8)的乘法函数Mul,输入GF(2^8)的两个元素a、b,输出a * b 。提示:回忆CINTA的Simple Multiplication。
#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;
}