S-AES加密实现

S-AES加密实现

S-AES是AES的简化版本,其只使用了16位的明文和16位的密钥进行加密。以下介绍S-AES的加密步骤。

测试数据:使用密钥1010 0111 0011 1011加密二进制明文0110 1111 0110 1011,得出二进制密文0000 0111 0011 1000

总体加密思路

简化版的AES和原本AES的步骤差不多,只是在轮数和一些运算的字节数上有不同。

S-AES加密的整体步骤示意图如下

在这里插入图片描述

接下来从扩展密钥到明文加密开始进行步骤阐述。

密钥扩展

由于只需要加密两轮,因此只需要扩展出两个密钥即可,包括原始密钥总共6个字节。扩展密钥步骤的示意图如下

在这里插入图片描述

将16位密钥分为左右两部分,每一部分各8位。记原始密钥为第0个密钥。

在计算第i个密钥时,首先将第i-1个密钥的右半部分(8位)进行左循环移位,即将第i-1个密钥的右半部分的左右4位进行交换,再将左循环移位后的第i-1个密钥的右半部分(8位)进行S盒置换,S-AES的S盒定义如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QD1YPZN-1665906607044)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20221016153622241.png)]

进行S盒置换后需要与轮常数进行异或,S-AES的轮常数定义为:第一轮加密的轮常数是【1000 0000】,第二轮加密的轮常数是【0011 0000】。

上述步骤就是示意图中函数g的步骤,将第i-1个密钥的右半部分(8位)执行完上述步骤后得到g(第i-1个密钥的右半部分),将其与第i-1个密钥的左半部分(8位)进行异或得到第i个密钥的左半部分。

i个密钥的右半部分由第i个密钥的左半部分与第i-1个密钥的右半部分进行异或得到。

计算出的两个扩展密钥是:

key1:0001 1100 0010 0111 
key2:0111 0110 0101 0001

明文加密

第0轮加密

只有将明文进行轮密钥加操作,即把明文按位与第0个密钥(原始输入密钥)进行异或。以下统称每一步骤处理完的都为明文。

第1轮加密

半字节代替

使用S盒将明文进行半字节的代替,就是一个简单的查表。具体步骤为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eqgzqjub-1665906607045)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20221016154406870.png)]

行位移

将一个字节排列成两行一列,即一行有四位,第二个字节按照这种方式形成第二列。第一行不进行移位,第二行循环左移位,一次移动4位。示例如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jzkSRINX-1665906607046)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20221016154521276.png)]

其中60是一个字节,4C是一个字节。

列混淆

简单来说列混淆就是乘上一个矩阵,运算定义在 G F ( 2 4 ) GF(2^4) GF(24) 上。列混淆矩阵是:

在这里插入图片描述

则与明文进行运算示意图为:

其中等式左边的右侧矩阵为明文, S 0 , 0 S_{0,0} S0,0 S 1 , 0 S_{1,0} S1,0 是一个字节,各为4位。 S 0 , 1 S_{0,1} S0,1 S 1 , 1 S_{1,1} S1,1 是一个字节,各为4位。执行乘法后可得到:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sArVGzXx-1665906607050)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20221016154711311.png)]

示意图右边即为列混淆后的结果。

第2轮加密

进行第二轮加密时,只有半字节代替,行移位和轮密钥加三个步骤,具体过程和第一轮一样,轮密钥加使用的是扩展密钥2即key2

经过上述步骤之后的结果就是密文了。

程序实现(C++)

#include <bits/stdc++.h>
using namespace std;

// TODO 实现x^nfx的函数
void x_de_n_fang_cheng_fx(int xfx[4], int a[4]) //* xfx是结果,a是上一步的结果
{
    //! 注意要取模
    //! 既约多项式是 x^4 + x + 1
    //* 保存四次乘法的系数
    if (a[0] == 0)
    {
        for (int i = 0; i < 3; i++)
            xfx[i] = a[i + 1];
    }
    else
    {
        //! 如果乘数首项不为1就需要将 b1x^2+b0x 与 x+1 进行异或
        xfx[1] = a[2];
        xfx[2] = a[3] == 1 ? 0 : 1;
        xfx[3] = 1;
    }
}
// TODO 乘法
int *chengfa(int a[4], int b[4])
{
    //* 储存结果的系数
    int *result = new int[4];
    for (int i = 0; i < 4; i++)
        result[i] = 0;

    //* 记录下x^nfx
    int xfx[4] = {0};
    x_de_n_fang_cheng_fx(xfx, a);
    int x2fx[4] = {0};
    x_de_n_fang_cheng_fx(x2fx, xfx);
    int x3fx[4] = {0};
    x_de_n_fang_cheng_fx(x3fx, x2fx);

    //* 现在需要根据多项式a和b开始异或
    if (b[0] == 1)
        for (int i = 0; i < 4; i++)
            result[i] ^= x3fx[i];
    if (b[1] == 1)
        for (int i = 0; i < 4; i++)
            result[i] ^= x2fx[i];
    if (b[2] == 1)
        for (int i = 0; i < 4; i++)
            result[i] ^= xfx[i];
    if (b[3] == 1)
        for (int i = 0; i < 4; i++)
            result[i] ^= a[i];
    return result;
}

const int s[4][4] = {
    {9, 4, 10, 11},
    {13, 1, 8, 5},
    {6, 2, 0, 3},
    {12, 14, 15, 7}};

const int tihuanwei[16][4] = {
    {0, 0, 0, 0},
    {0, 0, 0, 1},
    {0, 0, 1, 0},
    {0, 0, 1, 1},
    {0, 1, 0, 0},
    {0, 1, 0, 1},
    {0, 1, 1, 0},
    {0, 1, 1, 1},
    {1, 0, 0, 0},
    {1, 0, 0, 1},
    {1, 0, 1, 0},
    {1, 0, 1, 1},
    {1, 1, 0, 0},
    {1, 1, 0, 1},
    {1, 1, 1, 0},
    {1, 1, 1, 1}};
// const int tihuanwei[4][4][4] = {
//     {{1, 0, 0, 1},{0, 1, 0, 0},{1, 0, 1, 0},{1, 0, 1, 1}},
//     {{1, 1, 0, 1},{0, 0, 0, 1},{1,0,0,0},{0,1,0,1}},
//     {{0,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,1,1}},
//     {{1,1,0,0},{1,1,1,0},{1,1,1,1},{0,1,1,1}}};


//* 定义轮常数
int rcon1[8] = {1, 0, 0, 0, 0, 0, 0, 0};
int rcon2[8] = {0, 0, 1, 1, 0, 0, 0, 0};

int *yihuo8(int *a, int *b)//8位的异或
{
    int *t = new int[8];
    for (int i = 0; i < 8; i++)
        t[i] = a[i] ^ b[i];
    return t;
}

int *yihuo4(int *a, int *b)//4位的异或
{
    int *t = new int[4];
    for (int i = 0; i < 4; i++)
        t[i] = a[i] ^ b[i];
    return t;
}

void s_he_tihuan(int *temp) //使用s盒替换的函数,8位换
{
    int t1 = 2 * temp[0] + temp[1];
    int t2 = 2 * temp[2] + temp[3];
    int t3 = 2 * temp[4] + temp[5];
    int t4 = 2 * temp[6] + temp[7];
    int tihuan1 = s[t1][t2]; //记录替换后的数字
    int tihuan2 = s[t3][t4];
    //* 四位四位进行替换
    for (int i = 0; i < 4; i++)
        temp[i] = tihuanwei[tihuan1][i];
    for (int i = 0; i < 4; i++)
        temp[i + 4] = tihuanwei[tihuan2][i];
}

void zuoyi(int **temp) //循环左移
{
    //! 掉大坑!!!!注意半字节排列的方式,这里应该是第一字节的右半部分和第二字节的右半部分进行替换
    for(int i = 4;i < 8;i ++)
    {
        int t = temp[0][i];
        temp[0][i] = temp[1][i];
        temp[1][i] = t;
    }
}
int *g(int *temp, int *rcon) // temp是一个八位的数组,rcon是轮常数
{
    //! 注意这个temp是密钥,不能改动,要复制一个新的进行计算
    int *t = new int[8];
    for (int i = 0; i < 8; i++)
        t[i] = temp[i];
    //* 循环左移
    for (int i = 0; i < 4; i++)
    {
        int tt = t[i + 4];
        t[i + 4] = t[i];
        t[i] = tt;
    }

    //* 进行s盒替换
    s_he_tihuan(t);

    //* 进行轮常数异或
    return yihuo8(t, rcon);
}

void liehunxiao(int **mingwen)
{
    int si_de2jinzhi[4] = {0, 1, 0, 0};
    int *m00 = new int[4];
    int *m10 = new int[4];
    int *m01 = new int[4];
    int *m11 = new int[4];
    for (int i = 0; i < 4; i++)
    {
        m00[i] = mingwen[0][i];
        m10[i] = mingwen[0][i + 4];
        m01[i] = mingwen[1][i];
        m11[i] = mingwen[1][i + 4];
    }
    int *n00 = new int[4];
    int *n10 = new int[4];
    int *n01 = new int[4];
    int *n11 = new int[4];
    n00 = yihuo4(m00, chengfa(si_de2jinzhi, m10));//乘法结果是1011
    n10 = yihuo4(chengfa(si_de2jinzhi, m00), m10);//0101
    n01 = yihuo4(m01, chengfa(si_de2jinzhi, m11));//0100
    n11 = yihuo4(chengfa(si_de2jinzhi, m01), m11);//0010
    for (int i = 0; i < 4; i++)
    {
        mingwen[0][i] = n00[i];
        mingwen[0][i + 4] = n10[i];
        mingwen[1][i] = n01[i];
        mingwen[1][i + 4] = n11[i];
    }
}

void lunmiyaojia(int **mingwen, int **key)
{
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 8; j++)
            mingwen[i][j] ^= key[i][j];
}

//用于输出
void shuchu(int **a)
{
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 8; j++)
            cout << a[i][j] << ' ';
    cout << endl;
}

int main()
{
    //* 输入明文和密钥
    int **mingwen = new int *[2];
    for (int i = 0; i < 2; i++)
        mingwen[i] = new int[8];
    int **key = new int *[2];
    for (int i = 0; i < 2; i++)
        key[i] = new int[8];
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 8; j++)
            cin >> mingwen[i][j];
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 8; j++)
            cin >> key[i][j];

    //* 密钥扩展算法,由于只有三轮加密,第一轮还只使用了原始key
    int **key1 = new int *[2];
    for (int i = 0; i < 2; i++)
        key1[i] = new int[8];
    int **key2 = new int *[2];
    for (int i = 0; i < 2; i++)
        key2[i] = new int[8];

    key1[0] = yihuo8(key[0], g(key[1], rcon1));
    key1[1] = yihuo8(key1[0], key[1]);
    key2[0] = yihuo8(key1[0], g(key1[1], rcon2));
    key2[1] = yihuo8(key2[0], key1[1]);

    //* 第0轮的轮密钥加
    lunmiyaojia(mingwen, key);

    //*第一轮
    //* 明文半字节代替
    s_he_tihuan(mingwen[0]);
    s_he_tihuan(mingwen[1]);
    //* 明文的行移位
    zuoyi(mingwen);
    //* 明文的列混淆
    liehunxiao(mingwen);
    //* 明文的轮密钥加
    lunmiyaojia(mingwen, key1);

    //*第二轮
    //* 明文半字节代替
    s_he_tihuan(mingwen[0]);
    s_he_tihuan(mingwen[1]);
    
    //* 明文的行移位
    zuoyi(mingwen);
    //* 明文的轮密钥加
    lunmiyaojia(mingwen, key2);

    //* 现在的明文其实是密文了
    shuchu(mingwen);
    return 0;
}
/*
0 1 1 0 1 1 1 1 0 1 1 0 1 0 1 1
1 0 1 0 0 1 1 1 0 0 1 1 1 0 1 1
*/
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值