在GF(2^8)下可做任意两个数乘法的程序(一)(一)

2014-11-23 23:40:17 · 作者: · 浏览: 11
作业要求:
写一个GF(2^8)下可做任意两个数乘法的程序。
GF(2^8),也就是在一个字节上所做的乘法和加法都封闭的一个有限域。
在GF(2^8)上只有两种运算:异或加运算和乘法运算。
其中异或加运算就是1 xor 1 = 0, 0 xor 0 = 0, 1 xor 0 = 1。(原谅我的 嗦)
乘法运算的规则就是:
(1)A * 2的时候,A左移一位;A * 4 = (A * 2) * 2,A * 8 = ((A * 2) * 2) * 2,容易看出乘上2的n次幂是一个不断迭代的过程。
(2)那么A * 6的情况有如何?很简单,A * 6 = (A * 2) xor (A * 4),注意在该域中加法都是xor运算,而不是算术加运算。另外,可能有人会问:A * 4 = (A * 2) xor (A * 2) = 0,这不是和(1)冲突了吗?
原因在于:A * 6 = A * 00000110,其中00000110 = 00000100 xor 00000010,但是A * 4 = A * 00000100,00000100 != 00000010 xor 00000010 (= 00000000)。
(3)在乘法运算中,若乘数左移结果中第8位左边非0,例如10000000 * 00000100 = 10000000 * 2 * 2,其中10000000 * 2 = (1)00000000,结果溢出,所以要再和1BH进行异或加运算,即结果为00000000 xor 00011011 = 00011011。然后00011011 * 2 = 00110110即为结果。
错误做法:10000000 * 4 = (10)00000000 xor 00011011 = 00011011,为什么呢?因为10000000 * 2已经溢出,要先做溢出处理。
注:为什么是1BH?因为在AES的设计中开发者选用了不可约多项式m(x) = x^8 + x^4 + x^3 + x + 1,所以如果结果溢出就要再xor一个00011011(也就是1BH)。
在基本的运算法则搞懂以后,写程序就很简单了。
最近写OC写了很多,Java上学期也一直在写,反而C++好久没写了,突然又用回C++来写程序,还真的差点没转过弯来。所以现在趁着写博客的机会做下笔记。
好吧,回到程序来。
先来看看主函数,大致看看整个程序的流程:
[cpp]
int main()
{
int a[8], b[8], c[8], i=0;
LARGE_INTEGER start_t, stop_t, freq; // start_t表示计时开始时间,stop_t表示计时结束时间,freq为计时器的时钟频率
double exe_time;
QueryPerformanceFrequency(&freq);
// fprintf(stdout, "The frequency of your pc is %d.\n", freq.QuadPart);
char ch='y';
while(ch=='y'||ch=='Y')
{
// -- 清空之前的计算结果 --
for(i=0; i<8; i++)
{
c[i]=0; // 清空结果
}
state=0; // 清空当前左移位数
// -- 输入乘数a和b --
if(input(a, 'a')==0) // 如果输入a没有出错
{
if(input(b, 'b')==0) // 如果输入b没有出错
{
// -- 程序开始执行,开始计时 --
QueryPerformanceCounter(&start_t);
// -- 执行乘法运算 --
for(i=7; i>
=0; i--)
{
if(b[i]==1)
{
xor(c, leftshift(a, 7-i)); // 求和
}
}
// -- 输出运算结果 --
cout<<"运算结果为:";
for(i=0; i<8; i++)
{
cout<
}
// -- 程序结束执行,结束计时 --
QueryPerformanceCounter(&stop_t);
exe_time = 1e3*(stop_t.QuadPart-start_t.QuadPart)/freq.QuadPart;
cout<
fprintf(stdout, "计算用时:%fms.\n", exe_time);
}
}
// -- 是否继续执行程序 --
cout<
ch=cin.get();
if(cin.get()==10)
{
// 跳过输入y/n后的回车键,防止影响下面的输入
}
}
return 0;
}
结构非常清晰:清空之前的运算结果 —— 输入乘数a和b —— 执行乘法运算a * b —— 输出运算结果c以及计算时间 —— 是否循环执行。
首先来看看封装好的输入函数:
[cpp]
/*
* 分别输入两个GF(8)内的乘数
* 参数temp[]用于保存输入的二进制数组
* 参数name为变量名称,如a,b
* 返回类型为输入后的状态,若为0则成功,若非0则出错
*/
int input(int temp[], char name)
{
char c;
int i=0;
cout<<"请按8位二进制格式输入乘数"<
c=cin.get();
while(c!=10) // 若输入的不是回车
{
switch(c)
{
case '0':temp[i++]=0;break;
case '1':temp[i++]=1;break;
default:
cout<<"程序出错:数字输入错误,不是0或1";
cin.ignore((numeric_limits::max)(),'\n'); // 清除输入缓冲区中的所有内容
return 1;
}
c=cin.get();
if(c==10&&i!=8)
{
cout<<"程序出错:输入的数位数不等于8";
return 2;
}
}
return 0;
}
注意输入的数由于要在GF(2^8)内,所以必须符合要求:8位,每一位都是0或1,例如00000010。
若输入错误可以直接exit程序,这里做成了回