AES的S-BOX构造

利用GF(2^8)乘法逆元,以及矩阵运算,可以构造出AES的SBOX。

求乘法逆元的一般方法是利用扩展欧几里得定理,在这里我取了个巧。

因为我已经有了GF的指数表(见上一篇文),利用指数表可以轻易地构造出乘法逆元表。具体方法如下:

若 x = 3^m, y = 3^n, x 与 y 互为乘法逆元,则有x * y = 3^m * 3^n = 1 = 3^255(任意乘法逆元的255次方必定为1,有点类似费尔马小定理),则m+n=255

#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对应的值
    bool xb[8];
    unsigned char y = inv[x];
    //AES规定的常数项
    const bool N[8][8] = {1, 0, 0, 0, 1, 1, 1, 1,
                          1, 1, 0, 0, 0, 1, 1, 1,
                          1, 1, 1, 0, 0, 0, 1, 1,
                          1, 1, 1, 1, 0, 0, 0, 1,
                          1, 1, 1, 1, 1, 0, 0, 0,
                          0, 1, 1, 1, 1, 1, 0, 0,
                          0, 0, 1, 1, 1, 1, 1, 0,
                          0, 0, 0, 1, 1, 1, 1, 1};
    const bool C[8] = {1, 1, 0, 0, 0, 1, 1, 0};
    //将y转化为数组用作矩阵运算
    for(int i = 0; i < 8; i ++){
        xb[i] = (y&1);
        y >>= 1;
    }
    //矩阵乘法
    bool tmp[8];
    for(int i = 0; i < 8; i ++)tmp[i] = 0;
    for(int i = 0; i < 8; i ++){
        for(int j = 0; j < 8; j ++){
            tmp[i] ^= (N[i][j] & xb[j]);
        }
        tmp[i] ^= C[i];
    }
    //将数组结果转化为数值
    unsigned char result = 0;
    result |= tmp[7];
    for(int i = 6; i >= 0; i --){
        result <<= 1;
        if(tmp[i])result |= 1;
    }
    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;
}
C++
原文地址:https://www.cnblogs.com/7hat/p/3383546.html