数学领域有一个伽罗华(瓦)域,其广泛运用于加密算法中,本文则探索并记录C++实现形式如 G F ( 2 n ) GF(2^n) GF(2n)伽罗瓦域生成器及四则运算的步骤及方法。
一、什么是伽罗瓦域
不是本文重点,已经知道的略过,简单来说就是该域是一个有限数字集合,其上面加、异或是一个意思,乘、除跟我们正常理解的乘除略有差异, G F ( 2 n ) GF(2^n) GF(2n)伽罗瓦域就有 2 n 2^n 2n个值,详情请参阅以下:
二、模型定义
定义了一个模版类GFM,仅实现 G F ( 2 n ) GF(2^n) GF(2n)形式的,且n处于常用的2~15之间,上代码:
/*伽罗瓦域类GF(2^n)形式*/
template<uint8_t n>
class GFM {
private:
uint16_t* gf; //用于存放伽罗瓦域的值数组指针,x-1对应生成元的次幂,当x>0时,gf[x]=2^(x-1)
uint16_t* base; //用于存放伽罗瓦域值对应的下标指针,当x>0时,gf[base[x]]=x=2^(base[x]-1)
uint16_t N = power(2, n); //数组长度
bool overlap; //内置的本原多项式是否正确,默认正确为false
void init(uint16_t formuler); //初始化
int8_t operatorOrder(char c); //返回二元操作符优先级
uint16_t calculate(uint16_t a, uint16_t b, char opt); //进行二元运算
public:
//构造函数
GFM(uint16_t formuler=0) { //用户指定本原多项式构造,默认使用内置本原多项式
cout << "构造GF" << dec << N << endl;
if (n < 2 || n > 15) throw TypeException("幂次只有是在[2,15]之间");
gf = (uint16_t*)malloc(sizeof(uint16_t) * N);
base = (uint16_t*)malloc(sizeof(uint16_t) * N);
init(formuler); //使用内置本原多项式
}
~GFM() {
free(gf);
free(base);
gf = nullptr;
base =nullptr;
cout << "析构GF" << dec << N << endl;
}
void toString(); //将构造出的伽罗瓦域输出
uint16_t* getGF(); //获取伽罗瓦域值数组
uint16_t* getBase(); //获取值下标数组
uint16_t getLength(); //返回数组长度
uint16_t multi(uint16_t a1, uint16_t a2); //乘法
uint16_t adver(uint16_t a); //求乘法逆元
uint16_t calc(const char* expr); //求表达式的值
void matrixAdd(uint16_t* res, uint16_t* A1, uint16_t r1, uint16_t c1, uint16_t* A2, uint16_t r2, uint16_t c2); //矩阵加法
void matrixMulti(uint16_t* res, uint16_t* A1, uint16_t r1, uint16_t c1, uint16_t* A2, uint16_t r2, uint16_t c2); //矩阵乘法
};
在头文件里声明了模版类,也运用了动态内存分配技术,这样可以根据用户需求生成不同的伽罗瓦域。请看生成器的测试代码片断:
GFM<4> gf4;
gf4.toString();
GFM<8> gf8;
gf8.toString();
控制台输出结果片断如下:
构造GF16
GF[0]=0, GF[1]=1, GF[2]=2, GF[3]=4, GF[4]=8, GF[5]=3, GF[6]=6, GF[7]=c, GF[8]=b, GF[9]=5,
GF[a]=a, GF[b]=7, GF[c]=e, GF[d]=f, GF[e]=d, GF[f]=9,
BS[0]=0, BS[1]=1, BS[2]=2, BS[3]=5, BS[4]=3, BS[5]=9, BS[6]=6, BS[7]=b, BS[8]=4, BS[9]=f,
BS[a]=a, BS[b]=8, BS[c]=7, BS[d]=e, BS[e]=c, BS[f]=d,
构造GF256
GF[00]=00, GF[01]=01, GF[02]=02, GF[03]=04, GF[04]=08, GF[05]=10, GF[06]=20, GF[07]=40, GF[08]=80, GF[09]=1d,
GF[0a]=3a, GF[0b]=74, GF[0c]=e8, GF[0d]=cd, GF[0e]=87, GF[0f]=13, GF[10]=26, GF[11]=4c, GF[12]=98, GF[13]=2d,
GF[14]=5a, GF[15]=b4, GF[16]=75, GF[17]=ea, GF[18]=c9, GF[19]=8f, GF[1a]=03, GF[1b]=06, GF[1c]=0c, GF[1d]=18,
GF[1e]=30, GF[1f]=60, GF[20]=c0, GF[21]=9d, GF[22]=27, GF[23]=4e, GF[24]=9c, GF[25]=25, GF[26]=4a, GF[27]=94,
GF[28]=35, GF[29]=6a, GF[2a]=d4, GF[2b]=b5, GF[2c]=77, GF[2d]=ee, GF[2e]=c1, GF[2f]=9f, GF[30]=23, GF[31]=46,
GF[32]=8c, GF[33]=05, GF[34]=0a, GF[35]=14, GF[36]=28, GF[37]=50, GF[38]=a0, GF[39]=5d, GF[3a]=ba, GF[3b]=69,
GF[3c]=d2, GF[3d]=b9, GF[3e]=6f, GF[3f]=de, GF[40]=a1, GF[41]=5f, GF[42]=be, GF[43]=61, GF[44]=c2, GF[45]=99,
GF[46]=2f, GF[47]=5e, GF[48]=bc, GF[49]=65, GF[4a]=ca, GF[4b]=89, GF[4c]=0f, GF[4d]=1e, GF[4e]=3c, GF[4f]=78,
GF[50]=f0, GF[51]=fd, GF[52]=e7, GF[53]=d3, GF[54]=bb, GF[55]=6b, GF[56]=d6, GF[57]=b1, GF[58]=7f, GF[59]=fe,
GF[5a]=e1, GF[5b]=df, GF[5c]=a3, GF[5d]=5b, GF[5e]=b6, GF[5f]=71, GF[60]=e2, GF[61]=d9, GF[62]=af, GF[63]=43,
GF[64]=86, GF[65]=11, GF[66]=22, GF[67]=44, GF[68]=88, GF[69]=0d, GF[6a]=1a, GF[6b]=34, GF[6c]=68, GF[6d]=d0,
GF[6e]=bd, GF[6f]=67, GF[70]=ce, GF[71]=81, GF[72]=1f, GF[73]=3e, GF[74]=7c, GF[75]=f8, GF[76]=ed, GF[77]=c7,
GF[78]=93, GF[79]=3b, GF[7a]=76, GF[7b]=ec, GF[7c]=c5, GF[7d]=97, GF[7e]=33, GF[7f]=66, GF[80]=cc, GF[81]=85,
GF[82]=17, GF[83]=2e, GF[84]=5c, GF[85]=b8, GF[86]=6d, GF[87]=da, GF[88]=a9, GF[89]=4f, GF[8a]=9e, GF[8b]=21,
GF[8c]=42, GF[8d]=84, GF[8e]=15, GF[8f]=2a, GF[90]=54, GF[91]=a8, GF[92]=4d, GF[93]=9a, GF[94]=29, GF[95]=52,
GF[96]=a4, GF[97]=55, GF[98]=aa, GF[99]=49, GF[9a]=92, GF[9b]=39, GF[9c]=72, GF[9d]=e4, GF[9e]=d5, GF[9f]=b7,
GF[a0]=73, GF[a1]=e6, GF[a2]=d1, GF[a3]=bf, GF[a4]=63, GF[a5]=c6, GF[a6]=91, GF[a7]=3f, GF[a8]=7e, GF[a9]=fc,
GF[aa]=e5, GF[ab]=d7, GF[ac]=b3, GF[ad]=7b, GF[ae]=f6, GF[af]=f1, GF[b0]=ff, GF[b1]=e3, GF[b2]=db, GF[b3]=ab,
GF[b4]=4b, GF[b5]=96, GF[b6]=31, GF[b7]=62, GF[b8]=c4, GF[b9]=95, GF[ba]=37, GF[bb]=6e, GF[bc]=dc, GF[bd]=a5,
GF[be]=57, GF[bf]=ae, GF[c0]=41, GF[c1]=82, GF[c2]=19, GF[c3]=32, GF[c4]=64, GF[c5]=c8, GF[c6]=8d, GF[c7]=07,
GF[c8]=0e, GF[c9]=1c, GF[ca]=38, GF[cb]=70, GF[cc]=e0, GF[cd]=dd, GF[ce]=a7, GF[cf]=53, GF[d0]=a6, GF[d1]=51,
GF[d2]=a2, GF[d3]=59, GF[d4]=b2, GF[d5]=79, GF[d6]=f2, GF[d7]=f9, GF[d8]=ef, GF[d9]=c3, GF[da]=9b, GF[db]=2b,
GF[dc]=56, GF[dd]=ac, GF[de]=45, GF[df]=8a, GF[e0]=09, GF[e1]=12, GF[e2]=24, GF[e3]=48, GF[e4]=90, GF[e5]=3d,
GF[e6]=7a, GF[e7]=f4, GF[e8]=f5, GF[e9]=f7, GF[ea]=f3, GF[eb]=fb, GF[ec]=eb, GF[ed]=cb, GF[ee]=8b, GF[ef]=0b,
GF[f0]=16, GF[f1]=2c, GF[f2]=58, GF[f3]=b0, GF[f4]=7d, GF[f5]=fa, GF[f6]=e9, GF[f7]=cf, GF[f8]=83, GF[f9]=1b,
GF[fa]=36, GF[fb]=6c, GF[fc]=d8, GF[fd]=ad, GF[fe]=47, GF[ff]=8e,
BS[00]=00, BS[01]=01, BS[02]=02, BS[03]=1a, BS[04]=03, BS[05]=33, BS[06]=1b, BS[07]=c7, BS[08]=04, BS[09]=e0,
BS[0a]=34, BS[0b]=ef, BS[0c]=1c, BS[0d]=69, BS[0e]=c8, BS[0f]=4c, BS[10]=05, BS[11]=65, BS[12]=e1, BS[13]=0f,
BS[14]=35, BS[15]=8e, BS[16]=f0, BS[17]=82, BS[18]=1d, BS[19]=c2, BS[1a]=6a, BS[1b]=f9, BS[1c]=c9, BS[1d]=09,
BS[1e]=4d, BS[1f]=72, BS[20]=06, BS[21]=8b, BS[22]=66, BS[23]=30, BS[24]=e2, BS[25]=25, BS[26]=10, BS[27]=22,
BS[28]=36, BS[29]=94, BS[2a]=8f, BS[2b]=db, BS[2c]=f1, BS[2d]=13, BS[2e]=83, BS[2f]=46, BS[30]=1e, BS[31]=b6,
BS[32]=c3, BS[33]=7e, BS[34]=6b, BS[35]=28, BS[36]=fa, BS[37]=ba, BS[38]=ca, BS[39]=9b, BS[3a]=0a, BS[3b]=79,
BS[3c]=4e, BS[3d]=e5, BS[3e]=73, BS[3f]=a7, BS[40]=07, BS[41]=c0, BS[42]=8c, BS[43]=63, BS[44]=67, BS[45]=de,
BS[46]=31, BS[47]=fe, BS[48]=e3, BS[49]=99, BS[4a]=26, BS[4b]=b4, BS[4c]=11, BS[4d]=92, BS[4e]=23, BS[4f]=89,
BS[50]=37, BS[51]=d1, BS[52]=95, BS[53]=cf, BS[54]=90, BS[55]=97, BS[56]=dc, BS[57]=be, BS[58]=f2, BS[59]=d3,
BS[5a]=14, BS[5b]=5d, BS[5c]=84, BS[5d]=39, BS[5e]=47, BS[5f]=41, BS[60]=1f, BS[61]=43, BS[62]=b7, BS[63]=a4,
BS[64]=c4, BS[65]=49, BS[66]=7f, BS[67]=6f, BS[68]=6c, BS[69]=3b, BS[6a]=29, BS[6b]=55, BS[6c]=fb, BS[6d]=86,
BS[6e]=bb, BS[6f]=3e, BS[70]=cb, BS[71]=5f, BS[72]=9c, BS[73]=a0, BS[74]=0b, BS[75]=16, BS[76]=7a, BS[77]=2c,
BS[78]=4f, BS[79]=d5, BS[7a]=e6, BS[7b]=ad, BS[7c]=74, BS[7d]=f4, BS[7e]=a8, BS[7f]=58, BS[80]=08, BS[81]=71,
BS[82]=c1, BS[83]=f8, BS[84]=8d, BS[85]=81, BS[86]=64, BS[87]=0e, BS[88]=68, BS[89]=4b, BS[8a]=df, BS[8b]=ee,
BS[8c]=32, BS[8d]=c6, BS[8e]=ff, BS[8f]=19, BS[90]=e4, BS[91]=a6, BS[92]=9a, BS[93]=78, BS[94]=27, BS[95]=b9,
BS[96]=b5, BS[97]=7d, BS[98]=12, BS[99]=45, BS[9a]=93, BS[9b]=da, BS[9c]=24, BS[9d]=21, BS[9e]=8a, BS[9f]=2f,
BS[a0]=38, BS[a1]=40, BS[a2]=d2, BS[a3]=5c, BS[a4]=96, BS[a5]=bd, BS[a6]=d0, BS[a7]=ce, BS[a8]=91, BS[a9]=88,
BS[aa]=98, BS[ab]=b3, BS[ac]=dd, BS[ad]=fd, BS[ae]=bf, BS[af]=62, BS[b0]=f3, BS[b1]=57, BS[b2]=d4, BS[b3]=ac,
BS[b4]=15, BS[b5]=2b, BS[b6]=5e, BS[b7]=9f, BS[b8]=85, BS[b9]=3d, BS[ba]=3a, BS[bb]=54, BS[bc]=48, BS[bd]=6e,
BS[be]=42, BS[bf]=a3, BS[c0]=20, BS[c1]=2e, BS[c2]=44, BS[c3]=d9, BS[c4]=b8, BS[c5]=7c, BS[c6]=a5, BS[c7]=77,
BS[c8]=c5, BS[c9]=18, BS[ca]=4a, BS[cb]=ed, BS[cc]=80, BS[cd]=0d, BS[ce]=70, BS[cf]=f7, BS[d0]=6d, BS[d1]=a2,
BS[d2]=3c, BS[d3]=53, BS[d4]=2a, BS[d5]=9e, BS[d6]=56, BS[d7]=ab, BS[d8]=fc, BS[d9]=61, BS[da]=87, BS[db]=b2,
BS[dc]=bc, BS[dd]=cd, BS[de]=3f, BS[df]=5b, BS[e0]=cc, BS[e1]=5a, BS[e2]=60, BS[e3]=b1, BS[e4]=9d, BS[e5]=aa,
BS[e6]=a1, BS[e7]=52, BS[e8]=0c, BS[e9]=f6, BS[ea]=17, BS[eb]=ec, BS[ec]=7b, BS[ed]=76, BS[ee]=2d, BS[ef]=d8,
BS[f0]=50, BS[f1]=af, BS[f2]=d6, BS[f3]=ea, BS[f4]=e7, BS[f5]=e8, BS[f6]=ae, BS[f7]=e9, BS[f8]=75, BS[f9]=d7,
BS[fa]=f5, BS[fb]=eb, BS[fc]=a9, BS[fd]=51, BS[fe]=59, BS[ff]=b0,
析构GF256
析构GF16
内置了2个数组gf和base,如注释一样,gf[0] = 0是定义,gf[1] = 1即
2
0
2^0
20,这两个数组的内存申请在构造函数里,销毁内存则在析构函数里完成。构造函数里的init函数实现了对2个数组的初始化及本原多项式的取值,当参数formuler=0时,使用内置的本原多项式,当其不为0时,它就代表用户指定的本原多项式,比如用户想对GF(2^8)指定
x
8
+
x
7
+
x
6
+
x
+
1
x^8+x^7+x^6+x+1
x8+x7+x6+x+1作为其本原多项式,则将其编码为:
(
111000011
)
2
=
1
C
3
(111000011)_2=1C3
(111000011)2=1C3
template<uint8_t n>
void GFM<n>::init(uint16_t formuler) {
//初始化数据
memset(gf, 0, sizeof(uint16_t)*N);
memset(base, 0, sizeof(uint16_t)*N);
overlap = false;
*gf = 0;
*(gf+1) = 1;
*base = 0;
*(base+1) = 1;
uint16_t overflow;//溢出时异或的值
if (formuler != 0) {
overflow = formuler;
} else {
//选取内置对应的本原多项式
switch (n) {
case 2:
overflow = 0x07; //x^2+x+1
break;
case 3:
overflow = 0x0b; //x^3+x+1
break;
case 4:
overflow = 0x13; //x^4+x+1
break;
case 5:
overflow = 0x25; //x^5+x^2+1
break;
case 6:
overflow = 0x43; //x^6+x+1
break;
case 7:
overflow = 0x89; //x^7+x3+1
break;
case 8:
overflow = 0x11d; //x^8+x^4+x^3+x^2+1
break;
case 9:
overflow = 0x211; //x^9+x^4+1
break;
case 10:
overflow = 0x409; //x^10+x^3+1
break;
case 11:
overflow = 0x805; //x^11+x^2+1
break;
case 12:
overflow = 0x1053; //x^12+x^6+x^4+x+1
break;
case 13:
overflow = 0x201b; //x^13+x^4+x^3+x+1
break;
case 14:
overflow = 0x4443; //x^14+x^10+x^6+x+1
break;
case 15:
overflow = 0x8003; //x^15+x+1
break;
} //end of switch
} //end of if
//利用生成元进行生成
for (uint16_t i = 2; i < N; i++) {
*(gf+i) = *(gf+i-1) << 1; //乘2,gf[i] = gf[i-1]*2
if (*(gf+i) >= N) {
*(gf+i) ^= overflow;
}
if (*(base+*(gf+i))) overlap = true;
*(base+*(gf+i)) = i;
}
}
三、输出
不是重点,只贴代码:
template<uint8_t n>
void GFM<n>::toString() {
if (this->overlap) {
cout << "请检查本原多项式值" << endl;
return;
}
for (uint16_t i = 0; i < this->N; i++) {
cout << "GF[" << hex << setw((int)ceil(n/4.0)) << setfill('0') << i << "]=" << setw((int)ceil(n/4.0)) << setfill('0') << *(this->gf+i) << ", ";
if ((i + 1) % 10 == 0) { //每10个一换行
cout << endl;
}
}
cout << endl;
for (uint16_t i = 0; i < N; i++) {
cout << "BS[" << hex << setw((int)ceil(n/4.0)) << setfill('0') << i << "]=" << setw((int)ceil(n/4.0)) << setfill('0') << *(this->base+i) << ", ";
if ((i + 1) % 10 == 0) { //每10个一换行
cout << endl;
}
}
cout << endl;
}
四、四则运算
(一)基础二元运算
加、减都是直接异或就行,所以在我的类模版里找不到加、减函数,乘除函数实现如下:
/*乘法*/
template<uint8_t n>
uint16_t GFM<n>::multi(uint16_t a1, uint16_t a2) {
uint16_t e1 = *(this->base + a1) - 1; //2^e1 = a1
uint16_t e2 = *(this->base + a2) - 1;
return *(this->gf + (e1 + e2) % (this->N-1) + 1); //对应的生成元相应的幂次之和,除0以外,伽罗瓦域的值是有周期,这个周期就是N-1
}
/*乘法逆元,用于除法*/
template<uint8_t n>
uint16_t GFM<n>::adver(uint16_t a) {
if (a == 0) throw TypeException("除0错误");
if (a == 1) return 1;
uint16_t e1 = *(base + a) - 1; //2^e1 = a
uint16_t e2 = this->N - 1 - e1; //对于GF256,gf[255] * gf[2] == 1,所以它俩互为乘法逆元
return *(this->gf + e2 + 1);
}
(二)表达式运算
先使用calculate(uint16_t a, uint16_t b, char opt)函数对加减乘除进行封装,然后就是对表达式的解析了,有点像计算器的实现,这里囊括了小括号、十六进制、十进制、八进制数字、加减乘除运算符的解析:
/*计算表达式,要支持+-*\/()*/
template<uint8_t n>
uint16_t GFM<n>::calc(const char* expr) {
stack<char> stack_expr; //符号栈
stack<uint16_t> stack_num; //数值栈
uint16_t a, b, result; //用于运算的2个值
char ch; //当前操作符
stack_expr.push('#'); //先存入计算器表达式的底标志
for (int i = 0; *(expr + i) !=0; i++) {
ch = *(expr + i);
if (ch == '(') {
stack_expr.push(ch);
} else if (ch == ')') {
while (stack_expr.top() != '(' && stack_expr.top() != '#') {
ch = stack_expr.top();
stack_expr.pop();
b = stack_num.top();
stack_num.pop();
a = stack_num.top();
stack_num.pop();
stack_num.push(this->calculate(a, b, ch)); //将结果压栈用于下次运算
}
stack_expr.pop(); //退出'('
} else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { //字符串开头是数字
//判断进制
uint8_t base_flag = 10; //默认10进制
if (ch == '0') {
if (*(expr + i + 1) == 'x' || *(expr + i + 1) == 'X') {// 16进制标识
base_flag = 16;
} else if (*(expr + i + 1) >= '0' && *(expr + i + 1) <= '9') { //8进制标识
base_flag = 8;
}
}
//连续读取数字,包括16进制数
string num = "";
for (int j = i; *(expr + j) != 0 && ((*(expr + j) >= '0' && *(expr + j) <= '9') || (*(expr + j) >= 'a' && \
*(expr + j) <= 'f') || (*(expr + j) >= 'A' && *(expr + j) <= 'F')) || (*(expr + j) == 'x' || *(expr + j) == 'X'); j++) {
ch = *(expr + j);
num.append(1,ch); //将数字字符加入结尾
}
stack_num.push(stoi(num, nullptr, base_flag)); //将解析完的数字压栈
i += num.length()-1; //跳过数字,接着读取
} else if (ch == '+' || ch == '-' || ch == '^' || ch == '*' || ch == '/') { //加、减、异或、乘、除均为二元操作符,后压栈
if (this->operatorOrder(stack_expr.top()) >= this->operatorOrder(ch) && stack_expr.top() != '(') { //高优先级运算符
while (this->operatorOrder(stack_expr.top()) >= this->operatorOrder(ch) && stack_expr.top() != '(' &&
stack_num.size() > 1) { //若遇到前面压栈的运算符优先级高
b = stack_num.top();
stack_num.pop();
a = stack_num.top();
stack_num.pop();
stack_num.push(this->calculate(a, b, stack_expr.top())); //将结果压栈用于下次运算
stack_expr.pop(); //弹出已算过的运算符
}
}
stack_expr.push(ch); //将当前在读运算符压栈
}
}//end of for
//对栈中剩余数字进行运算
while (stack_expr.size() > 0 && '#' != stack_expr.top() && stack_num.size() > 1) {
ch = stack_expr.top();
stack_expr.pop();
b = stack_num.top();
stack_num.pop();
a = stack_num.top();
stack_num.pop();
stack_num.push(this->calculate(a, b, ch)); //将结果压栈用于下次运算
}
result = stack_num.top();
stack_num.pop();
stack_expr.pop(); //弹出'#'
if (stack_num.size() > 0 || stack_expr.size() > 0) { //运算符、数字数量不匹配
throw TypeException("错误表达式");
}
return result;
}
以下正常测试及鲁棒性测试:
cout << gf8.calc("2*0xe +3*9+1*0xd+1*0xb") << endl; //空格也是鲁棒性测试的一部分
cout << gf8.calc("1* 0xe+2*9+3*0xd+1*0xb") << endl;
//测试抛出异常
// cout << gf8.calc("(2*0xe+3*9+1*0xd+1*0xb") << endl;
// cout << gf8.calc("1*0xe+-2*9+3*0xd++1*0xb") << endl;
// GFM<16> gf16;
// gf16.toString();
// GFM<1> gf1;
// gf1.toString();
测试结果:
1
0
(三)矩阵运算
实现了矩阵加法和乘法:
/*矩阵加法运算,A1为r行c列,A2为m行n列,运算结果res*/
template<uint8_t n>
void GFM<n>::matrixAdd(uint16_t* res, uint16_t* A1, uint16_t r1, uint16_t c1, uint16_t* A2, uint16_t r2, uint16_t c2) {
if (r1 != r2 || c1 != c2) throw TypeException("矩阵输行列不一致");
for (uint16_t i = 0; i < r1 * c1; i++) {
*(res+i) = *(A1+i)^*(A2+i);
}
}
/*矩阵乘法运算,A1为r行c列,A2为m行n列,运算结果res为r行n列*/
template<uint8_t n>
void GFM<n>::matrixMulti(uint16_t* res, uint16_t* A1, uint16_t r1, uint16_t c1 , uint16_t* A2, uint16_t r2, uint16_t c2) {
if (r1 != c2 || c1 != r2) throw TypeException("矩阵输行列不一致");
for (uint16_t i = 0; i < r1; i++) { //A1逐行
for (uint16_t k = 0; k < c2; k++) { //A2逐列
uint16_t temp = 0;
for (uint16_t j = 0; j < c1 ; j++) { //A1一行中逐列
temp ^= this->multi(*(A1 + i * c1 + j),*(A2 + j * c2 + k)); //A1一行中逐列、A2一列中逐行
}
*(res + i * c2 + k) = temp;
}
}
}
测试代码:
uint16_t res[16];
uint16_t a[16] = {2,3,1,1,1,2,3,1,1,1,2,3,3,1,1,2};
uint16_t b[16] = {0xe,0xb,0xd,9,9,0xe,0xb,0xd,0xd,9,0xe,0xb,0xb,0xd,9,0xe};
gf8.matrixAdd(res, a, 4, 4, b, 4, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++){
cout << hex << res[i*4+j] << " ";
}
cout << endl;
}
gf8.matrixMulti(res, a, 4, 4, b, 4, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++){
cout << hex << res[i*4+j] << " ";
}
cout << endl;
}
a、b这2个在GF(256)域内的互为乘法逆矩阵,即
[
02
03
01
01
01
02
03
01
01
01
02
03
03
01
01
02
]
×
[
0
e
0
b
0
d
09
09
0
e
0
b
0
d
0
d
09
0
e
0
b
0
b
0
d
09
0
e
]
\begin{bmatrix} 02&03&01&01\\ 01&02&03&01\\ 01&01&02&03\\ 03&01&01&02 \end{bmatrix} \times \begin{bmatrix} 0e&0b&0d&09\\ 09&0e&0b&0d\\ 0d&09&0e&0b\\ 0b&0d&09&0e \end{bmatrix}
02010103030201010103020101010302
×
0e090d0b0b0e090d0d0b0e09090d0b0e
=
[
1
0
0
0
0
1
0
0
0
0
1
0
0
0
0
1
]
=\begin{bmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{bmatrix}
=
1000010000100001
测试结果:
c 8 c 8
8 c 8 c
c 8 c 8
8 c 8 c
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

1005

被折叠的 条评论
为什么被折叠?



