GF(2^8)这是啥我就不多做解释了,某度某科与各位大佬的博客都有写,,,,
加法运算,超级简单,就是一个异或运算就解决了,这里主要说下乘法运算。
我们先规定下这里的模乘的不可约多项式为m=x^8+x^4+x^3+x+1
我说下在这里我的做法:
因为是二进制上的转化,所以我们可以先将输入的两个十六进制串转化为二进制,转化完后对它们进行乘法运算(下面会有样例)得到多项式mx,然后找到最高幂的次数,比较一下与8的差值,得到差c,再将不可约多项式乘上x^c,再与mx进行异或运算,再寻找下一个最高项的指数,重复以上运算,直到出现最高项的指数小于8。然后就得到了答案。
例如:0x57*0x83=x^13+x^11+x^9+x^8+x^6+x^5+x^4+x^3+x+1, 用二进制表示:010101101111011
第一次:最高幂为13,13-8=5,所以将m*x^5=x^13+x^9+x^8+x^6+x^5 用二进制表示:010001101100000
异或得到 000100000011011即多项式:x^11+x^4+x^3+x+1
第二次:最高幂为11,11-8=3,所以将m*x^3=x^11+x^7+x^6+x^4+x^3 二进制表示:000100011011000
异或得到:00000001100001即多项式:x^7+x^6+1,
第三次:最高幂为7小于8,不满足,取模结束
得到答案用十六进制表示为0xC1
经过运算暂未发现错误答案,若发现,还望各位大佬告知,菜鸡在此感谢万分
实现代码:
///2的8次方有限域内的加乘
///指定x^8+x^4+x^3+x+1为不可约多项式
///加法原理:异或操作
///乘法原理:循环操作,具体看过程
#include
#include
#include
#include
#define ll long long
const int maxn=1010;
char sa[maxn],sb[maxn],sc[maxn];///要进行运算的十六进制串
int a[maxn],b[maxn],c[maxn];///a,b用来接收两个串转化成的二进制,c为中转及保存加法值
int sl[maxn];///用十六个空间存两个二进制相乘
int NB[maxn];///为不可约多项式的二进制表示
void init()///初始化
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(sa,0,sizeof(sa));
memset(sb,0,sizeof(sb));
memset(sc,0,sizeof(sc));
memset(sl,0,sizeof(sl));
}
void changebit(char s[],int flag)///将十六进制转为二进制(验证正确)
{
int l=0;
for(int i=2; i<4; i++)
{
memset(c,0,sizeof(c));
int n=s[i],cnt=0;
if(s[i]>='A')
n-=55;
else
n-='0';
while(n)
{
c[cnt++]=n%2;
n/=2;
}
if(flag==1)
{
for(int j=3; j>=0; j--)
a[l++]=c[j];
}
else
{
for(int j=3; j>=0; j--)
b[l++]=c[j];
}
}
}
void bitchange()///将二进制转为十六进制
{
sc[0]='0',sc[1]='x';
int l=2;
for(int i=0; i<8; i++)
{
if((i+1)%4==0)
{
int ans=c[i-3]*8+c[i-2]*4+c[i-1]*2+c[i];
if(ans>9)
sc[l++]='A'+ans-10;
else
sc[l++]=ans+'0';
}
}
}
void cy()///乘法运算
{
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
if(a[i]&&b[j])
{
if(sl[14-i-j]==1)///最大两个x^7相乘
sl[14-i-j]=0;///如果已经有值则二进制归0
else
sl[14-i-j]=1;
}
}
}
}
int jisuan()///模拟过程
{
int ans=0,i;///用来记录最大项大于8多少次
for( i=16; i>=0; i--)
{
if(sl[i]==1)
{
ans=i-8;
break;
}
}
if(ans<0||(ans==0&&sl[0]==0))
return 1;///计算结束
else
NB[ans]=1,NB[1+ans]=1,NB[3+ans]=1,NB[4+ans]=1,NB[8+ans]=1;
return 0;
}
void jiafa()
{
init();
printf("请输入要进行运算的一字节十六进制串(以0x为开头)
");
scanf("%s %s",sa,sb);
changebit(sa,1),changebit(sb,2);
for(int i=0; i<8; i++)
c[i]=a[i]^b[i];
bitchange();
printf("
得到十六进制相加结果:%s
",sc);
}
void chenfa()
{
init();
printf("请输入要进行运算的一字节十六进制串(以0x为开头)
");
scanf("%s %s",sa,sb);
changebit(sa,1),changebit(sb,2);
cy();
while(1)
{
memset(NB,0,sizeof(NB));
if(jisuan())
{
for(int i=0; i<8; i++)
c[7-i]=sl[i];
break;
}
else
for(int i=0; i<16; i++)
sl[i]^=NB[i];
}
bitchange();
printf("
得到答案:%s
",sc);
}
int main()
{
while(true)
{
printf("请选择进行的运算: 0.退出运算 1.加法运算 2.乘法运算
");
int ch;
scanf("%d",&ch);
switch(ch)
{
case 0:
system("cls");
printf("
欢迎使用!
");
exit(0);
case 1:
system("cls");
jiafa();
break;
case 2:
system("cls");
chenfa();
break;
default :
system("cls");
printf("
输入错误!请重新输入:
");
break;
}
}
return 0;
}
上面是笨办法,就是模拟做出来的,下面是简单方法:具体原理参考这位大佬:
https://blog.csdn.net/bupt073114/article/details/27382533
我就是用他的原理自己实现了一波
代码:
#include
#include
void jiafa()
{
printf("请输入两个十六进制串:
");
int hex1,hex2;
scanf("%x%x",&hex1,&hex2);
printf("
得到有限域内相加结果 : %#X
",hex1^hex2);
}
void chenfa()
{
int a[16],b[16],s[32];
printf("请输入两个十六进制串:
");
int hex1,hex2;
scanf("%x%x",&hex1,&hex2);
int n=hex2,cnt=0;
while(n)///转化为二进制
{
s[cnt++]=n%2;
n/=2;
}
a[1]=0x01,b[1]=hex1;
for(int i=2; i<=8; i++)
a[i]=a[i-1]<<1;///得到0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80
for(int i=2; i<=8; i++)
{
if(b[i-1]&0x80)///如果最高为为1就对不可约多项式取模,否则直接左移
b[i]=((b[i-1]<<1)^0x1B);
else
b[i]=b[i-1]<<1;
b[i]&=0xFF;///直接取后两位
}
int hex=0x00;
for(int i=7; i>=0; i--)
{
if(s[i]==1)///当二进制的这一位为1的时候才能异或
hex^=b[i+1];
}
printf("
得到有限域内相乘结果 : %#X
",hex);
}
int main()
{
while(1)
{
printf("请选择进行的运算: 0.退出运算 1.加法运算 2.乘法运算
");
int ch;
scanf("%d",&ch);
switch(ch)
{
case 0:
system("cls");
printf("
欢迎使用!
");
exit(0);
case 1:
system("cls");
jiafa();
break;
case 2:
system("cls");
chenfa();
break;
default :
system("cls");
printf("
输入错误!请重新输入:
");
break;
}
}
return 0;
}