密码学AES算法_S盒_C值搜索

文章目录

效果

代码

#include<stdio.h>
//SBox
int SBox[16][16];
//m(x)
int M_x = 283;
//m(x)_set
int M_x_set[30] = {283,285,299,301,313,319,333,351,355,357,361,369,375,379,391,395,397,415,419,425,433,445,451,463,471,477,487,499,501,505};
//M_x_set长度
int Len_M_x_set = 30;

char dec2Hex(int n);                           //10进制转16进制
void init();                                   //SBox初始化
void exgcd();                                  //求逆元
int numb_bits(int v);                          //十进制的二进制位数
int polydivide(int a, int b, int* remainder);  //多项式除法
int polyMulti(int a, int b);                   //多项式乘法
int Ext_Euclid(int a, int b);                  //扩展欧几里得算法
void transforms(int* c);                       //位变换
int transform(int num, int* c);
int encrypt(int clear);                        //加密算法
void search_c(int *c_array, int *pos);         //c值搜寻
void ferfect_c();                              //完美c值搜寻
void show_c();                                 //c值展示
void decto2(int* c, int flag);                 //二进制加法



int main() {
    show_c();
	return 0;
}

//输入明文,输出密文
int encrypt(int clear) {
    return SBox[clear / 16][clear % 16];
}
//c值搜寻
void search_c(int* c_array, int *pos){
    int c[8], flag;
    for (int i = 0; i < 256;i++) {
        decto2(c, i); //二进制加法
        init();          //SBox初始化
        exgcd();         //求逆元
        transforms(c);   //位变换
        flag = 0;
        for (flag; flag< 256;flag++) {

            if (flag == encrypt(flag) || 255 - flag == encrypt(flag)) break;
        }
        if(flag==256) c_array[++(*pos)] = i;
    }
}

//完美c值搜寻
void ferfect_c(){
    //初始化
    int c_array[255], perfect_c_0_1[16][16], pos;
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            perfect_c_0_1[i][j] = 0;
        }
    }

    //c值搜寻
    for (int i = 0; i < Len_M_x_set; i++) {
        pos = -1;
        search_c(c_array, &pos);
        for (int j = 0; j <= pos; j++) {
            perfect_c_0_1[c_array[j] / 16][c_array[j] % 16]++;
        }
    }

    //c值展示
    printf("perfect_c_0_1矩阵展示:");
    for (int i = 0; i < 16; i++) {
        printf("\n");
        for (int j = 0; j < 16; j++) {
            printf("%d ", perfect_c_0_1[i][j]);
        }
    }
}

void show_c() {
    int c_array[255], c_0_1[16][16], pos = -1;
    search_c(c_array, &pos);
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            c_0_1[i][j] = 0;
        }
    }

    //满足条件c置1
    for (int i = 0; i <= pos; i++) {
        c_0_1[c_array[i] / 16][c_array[i] % 16] = 1;
    }

    //c展示
    int m_x[9];
    for (int i = 8; i >= 0;i--) {
        m_x[i] = M_x % 2;
        M_x = (M_x - M_x % 2) / 2;
    }
    printf("\nm_x多项式:");
    for (int i = 0; i < 9; i++) {
        printf("%d ",m_x[i]);
    }
    printf("\n符合条件的c值共有 %d 个", pos + 1);
    printf("\nc_0_1矩阵展示:");
    for (int i = 0; i < 16; i++) {
        printf("\n");
        for (int j = 0; j < 16; j++) {
            printf("%d ", c_0_1[i][j]);
        }
    }
}

//十进制转二进制
void decto2(int *c, int flag) {
    for (int i = 7; i >= 0;i--) {
        c[i] = flag % 2;
        flag = (flag - flag % 2) / 2;
    }
}

// 将输入的整数的16进制对应字符返回,输入的整数在0~15之间
char dec2Hex(int n) {
    if (n >= 0 && n <= 9)return 48 + n;
    switch (n) {
    case 10:return 'A'; break;
    case 11:return 'B'; break;
    case 12:return 'C'; break;
    case 13:return 'D'; break;
    case 14:return 'E'; break;
    case 15:return 'F'; break;
    }
    return ' ';
}

void init() {
    // SBox初始化
    for (int i = 0; i < 16; i++) {
        if (i != 0)SBox[i][0] = SBox[i - 1][15] + 1;
        for (int j = 1; j < 16; j++) {
            SBox[i][j] = SBox[i][j - 1] + 1;
        }
    }
    
    //SBox打印
    /*printf("初始化:\n");
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            printf("%c%c ", dec2Hex(SBox[i][j] / 16), dec2Hex(SBox[i][j] % 16));
        }
        printf("\n");
    }
    printf("\n");
    */
}

void exgcd() {
    //printf("求逆元:\n");
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            // 重要的就是Ext_Euclid算法,是拓展欧几里得算法,用于求整数在域上的逆元,参考的网上前辈的代码,感谢。
            SBox[i][j] = Ext_Euclid(SBox[i][j], M_x);
            // dec2Hex:将整数转为16进制
            //printf("%c%c ", dec2Hex(SBox[i][j] / 16), dec2Hex(SBox[i][j] % 16));
        }
        //printf("\n");
    }
}
//计算一个十进制数的二进制表示时的位数有多大
//直接计算右移了多少位就可
int numb_bits(int v)
{
    int count = 0;
    while (v > 0)
    {
        v = v >> 1;
        count++;
    }
    return count;
}
//多项式除法
int polydivide(int a, int b, int* remainder)
{
    int tmp;
    int c = numb_bits(a) - numb_bits(b);
    int value = 0;
    while (c >= 0)
    {
        value = (1 << c) | value; //计算商,这时计算的c值就是每一个是1的位置,直接与1相与,就可以将其设置为1
        tmp = b;//将被除数向左移c位再与a相与,并赋给a
        tmp = tmp << c;
        a = a ^ tmp;
        c = numb_bits(a) - numb_bits(b);
    }
    *remainder = a;
    return value;
}
//多项式乘法
int polyMulti(int a, int b)
{
    int value = a;
    int result = a;
    int r;
    if (a == 0 || b == 0)
        return 0;
    r = b % 2;
    b = b / 2;
    if (!r)  //判断最后一位是0还是1,是0的话result就等于0
        result = 0;
    while (b)
    {
        r = b % 2;
        b = b / 2;
        if (value >> 7) //b7为1,就要与00011011相与
            value = (value << 1) & 0xff ^ 27;
        else
            value = (value << 1) & 0xff;
        if (r) //位为1的结果就参加异或运算
            result = result ^ value;
    }

    return result;
}
//扩展的欧几里德算法
int Ext_Euclid(int a, int b)
{
    int tmp;
    if (a < b)
    {
        tmp = a;
        a = b;
        b = tmp;
    }
    int x0 = 1, y0 = 0, x1 = 0, y1 = 1;//初始化条件
    int tmp1, tmp2;
    int r1 = a, r2 = b, q1;
    int i = 1;
    //下面直接用扩展欧几里德算法来做
    while (r2)
    {
        tmp1 = r2;
        q1 = polydivide(r1, r2, &r2);//r1对r2进行多项式除法,商存在q1,余数存在r2
        r1 = tmp1;//这步比较重要,就是r1要变成上一次除法的被除数
        tmp1 = x1;
        tmp2 = y1;
        x1 = x0 ^ polyMulti(q1, x1);  //计算v,w;每一个v(x)*f(x)+w(x)*g(x)=1成立
        y1 = y0 ^ polyMulti(q1, y1);
        x0 = tmp1;
        y0 = tmp2;
        i++;
    }
    return y0;
}

void transforms(int *c) {
    //printf("\n位变换:\n");
    for (int i = 0, j = 0; i < 16; i++) {
        for (j = 0; j < 16; j++) {
            SBox[i][j] = transform(SBox[i][j], c);
            //printf("%c%c ", dec2Hex(SBox[i][j] / 16), dec2Hex(SBox[i][j] % 16));
        }
        //printf("\n");
    }
}

int transform(int num, int *c) {
    int n[8];
    int b[8];
    // int c[8] = {0,1,1,0,0,0,1,1};
    // int c[8] = { 1,1,0,0,0,1,1,0 };
    int i = 0;
    for (i = 0; i < 8; i++) {
        n[i] = num % 2;
        num /= 2;
    }
    int j = 1;
    for (i = 0, num = 0; i < 8; i++) {
        // 使用二进制移位来做更好,偷懒就不做了。
        b[i] = n[i] ^ n[(i + 4) % 8]
            ^ n[(i + 5) % 8]
            ^ n[(i + 6) % 8]
            ^ n[(i + 7) % 8]
            ^ c[i];
        num += b[i] * j;
        j *= 2;
    }
    return num;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值