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盒定义如下:
进行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盒将明文进行半字节的代替,就是一个简单的查表。具体步骤为:
行位移
将一个字节排列成两行一列,即一行有四位,第二个字节按照这种方式形成第二列。第一行不进行移位,第二行循环左移位,一次移动4
位。示例如下:
其中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位。执行乘法后可得到:
示意图右边即为列混淆后的结果。文章来源:https://www.toymoban.com/news/detail-401133.html
第2轮加密
进行第二轮加密时,只有半字节代替,行移位和轮密钥加三个步骤,具体过程和第一轮一样,轮密钥加使用的是扩展密钥2即key2
。文章来源地址https://www.toymoban.com/news/detail-401133.html
经过上述步骤之后的结果就是密文了。
程序实现(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
*/
到了这里,关于S-AES加密实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!