之前写过SBOX的构造,后来看到别人的优秀思路,借鉴过来重新改了一点。
原文地址:http://www.cnblogs.com/7hat/p/3383546.html
主要是将矩阵运算改为列运算之和,提高了效率。
#include<iostream> #include<fstream> #include <iomanip> using namespace std; unsigned char exp[256], log[256], inv[256]; unsigned char GFmul(unsigned char a, unsigned char b){ //GF(2^8) 乘法 unsigned char result = 0; if((b&1) == 1)result = a; b >>= 1; for(int i = 1; i < 8; i ++){ if(a > 127){ a = (a << 1) ^ 0x1b; } else{ a <<= 1; } if((b&1) == 1){ result ^= a; } b >>= 1; } return result; } void generateMulTab(){ //选择生成元3作为构造乘法表的基础 const int N = 3; exp[1] = N; log[N] = 1; unsigned char tmp = N; for(int i = 2; i < 256; i ++){ tmp = GFmul(tmp, N); exp[i] = tmp; log[tmp] = i; } } void generateMulInverse(){ //利用exp来构造乘法逆元 inv[0] = 0; inv[1] = 1; //若3^m * 3^n = 1 = 3^255,则 m + n = 255 for(int i = 1; i < 255; i ++){ inv[exp[i]] = exp[255-i]; } } unsigned char SBoxValue(unsigned char x){ //返回SBOX对应的值 unsigned char y = inv[x]; unsigned char result = 0; unsigned char c = 0x1f; //常数矩阵的第一列 while(y){ //将矩阵运算转化为列运算之和,因为y只是一个"一维"的矩阵 if(y&1){ //yi 表示是否要加上对应ci的列 result ^= c; } y >>= 1; //循环左移为下一列元素 c = (c<<1) | (c>>7); } result ^= 0x63; return result; } int main(){ //单元测试,输出SBOX的全部值 generateMulTab(); generateMulInverse(); unsigned char SBox[16][16]; for(int i = 0; i < 16; i ++){ for(int j = 0; j < 16; j ++){ unsigned char tmp = i*16 + j; SBox[i][j] = SBoxValue(tmp); } } ofstream write("Test.txt"); for(int i = 0; i < 16; i ++){ for(int j = 0; j < 16; j ++){ write<<setiosflags(ios::left)<<setw(4)<<hex<<(int)SBox[i][j]; } write<<endl; } write.close(); return 0; }