在写AES的过程中,主要是通过写算法的过程来理解AES的原理,算法比较笨拙,能成功加密书上的例子,但解密不对,尚未找到错误原因。
发出来的目的就是对自己学习的记录。

  • 在AES中共用到五个数据度量单位:位,字节,字,分组,态。

位:二进制的0和1

字节:一组8位呃二进制

字:由四个字节组成

分组:128位

态:态和分组是通一个意思,由16个字节组成,但被表示成4*4字节的一个矩阵,因此态的每一行每一列都是一个字,矩阵的某一点就是一个字节。

  • S盒的来源

(1)态中的每个字节的前四位与后四位做有限域 G F ( 2 8 ) GF(2^8) GF(28)上的乘法的结果

(2)乘法的结果求逆

(3)对求逆得出的结果中的每一位做仿射变换。

  • 由分组变成态(4*4)的过程中,是从左至右,从上到下进行排序的。即先把第一列填好,才填第二列的顺序来

1.加密运算

(1)字节替代(SubBytes)

态中的每个字节,前四位的十六进制为S盒的横坐标,后四位的十六进制为S的列坐标,找出S盒替换的结果。

(2)行移位(ShiftRows)

以字节为单位进行循环左移动

第一行每个字节不移动

第二行循环左移一个字节

第三行循环左移两个字节

第四行循环左移三个字节

(3)列混淆(MixColumns)

S态的4*4矩阵与一个矩阵常量CloumM做矩阵乘法运算(线性代数的内容),但注意S的第一行与CloumM的第一列的乘积过后在异或的值为结果的(1,1)的值。

(4)轮密钥加(AddRoundKey)

S态中的每一列的每一个字节与对应的密钥进行异或

2.密钥的扩展

(1) RotWord():输入四个字节(32位)按字节左循环一个字节

(2) SubWord():基于S盒对(1)的字进行S盒替代

(3) 将(2)的结果与轮常量R[i/4]异或

(4) 将(3)的结果与w[i-4]异或

3.解密流程

解密算法与加密算法类似,主要区别在于轮密钥要逆序使用,四个基本运算都有对应的逆运算。

4.算法框图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K49j7bWx-1654878440223)(https://raw.githubusercontent.com/togetherhkl/Mypictures/main/20220611001611.jpg)]

5.算法实现C++代码

1.只实现了对128bit的十六进制进行加密,没有实现对文本的加密,没有利用分组模式

2.加密的过程能与书上给出的例子一致加密。参考书:《应用密码学》/胡向东,魏琴芳,胡蓉编著. —4版. —北京:电子工业出版社,2019.6 :127

3.解密部分不正确,尚未找到代码错误

4.整个算法是写在头文件中的,对加密算法的测试需在main()中调用AESEncryptionTest()函数

5.算法在求有限域 G F ( 2 8 ) GF(2^8) GF(28)上的乘法是用的是查表得方法,参照:《应用密码学》/胡向东,魏琴芳,胡蓉编著. —4版. —北京:电子工业出版社,2019.6 :111 表5-12

运行结果

#pragma once
#include<iostream>
#include<string>
using namespace std;static const string S[16][16] = { //S盒替换"63", "7c", "77", "7b", "f2", "6b", "6f", "c5", "30", "01", "67", "2b", "fe", "d7", "ab", "76","ca", "82", "c9", "7d", "fa", "59", "47", "f0", "ad", "d4", "a2", "af", "9c", "a4", "72", "c0","b7", "fd", "93", "26", "36", "3f", "f7", "cc", "34", "a5", "e5", "f1", "71", "d8", "31", "15","04", "c7", "23", "c3", "18", "96", "05", "9a", "07", "12", "80", "e2", "eb", "27", "b2", "75","09", "83", "2c", "1a", "1b", "6e", "5a", "a0", "52", "3b", "d6", "b3", "29", "e3", "2f", "84","53", "d1", "00", "ed", "20", "fc", "b1", "5b", "6a", "cb", "be", "39", "4a", "4c", "58", "cf","d0", "ef", "aa", "fb", "43", "4d", "33", "85", "45", "f9", "02", "7f", "50", "3c", "9f", "a8","51", "a3", "40", "8f", "92", "9d", "38", "f5", "bc", "b6", "da", "21", "10", "ff", "f3", "d2","cd", "0c", "13", "ec", "5f", "97", "44", "17", "c4", "a7", "7e", "3d", "64", "5d", "19", "73","60", "81", "4f", "dc", "22", "2a", "90", "88", "46", "ee", "b8", "14", "de", "5e", "0b", "db","e0", "32", "3a", "0a", "49", "06", "24", "5c", "c2", "d3", "ac", "62", "91", "95", "e4", "79","e7", "c8", "37", "6d", "8d", "d5", "4e", "a9", "6c", "56", "f4", "ea", "65", "7a", "ae", "08","ba", "78", "25", "2e", "1c", "a6", "b4", "c6", "e8", "dd", "74", "1f", "4b", "bd", "8b", "8a","70", "3e", "b5", "66", "48", "03", "f6", "0e", "61", "35", "57", "b9", "86", "c1", "1d", "9e","e1", "f8", "98", "11", "69", "d9", "8e", "94", "9b", "1e", "87", "e9", "ce", "55", "28", "df","8c", "a1", "89", "0d", "bf", "e6", "42", "68", "41", "99", "2d", "0f", "b0", "54", "bb", "16" };static const string InvS[16][16] = { //逆S盒"52", "09", "6a", "d5", "30", "36", "a5", "38", "bf", "40", "a3", "9e", "81", "f3", "d7", "fb","7c", "e3", "39", "82", "9b", "2f", "ff", "87", "34", "8e", "43", "44", "c4", "de", "e9", "cb","54", "7b", "94", "32", "a6", "c2", "23", "3d", "ee", "4c", "95", "0b", "42", "fa", "c3", "4e","08", "2e", "a1", "66", "28", "d9", "24", "b2", "76", "5b", "a2", "49", "6d", "8b", "d1", "25","72", "f8", "f6", "64", "86", "68", "98", "16", "d4", "a4", "5c", "cc", "5d", "65", "b6", "92","6c", "70", "48", "50", "fd", "ed", "b9", "da", "5e", "15", "46", "57", "a7", "8d", "9d", "84","90", "d8", "ab", "00", "8c", "bc", "d3", "0a", "f7", "e4", "58", "05", "b8", "b3", "45", "06","d0", "2c", "1e", "8f", "ca", "3f", "0f", "02", "c1", "af", "bd", "03", "01", "13", "8a", "6b","3a", "91", "11", "41", "4f", "67", "dc", "ea", "97", "f2", "cf", "ce", "f0", "b4", "e6", "73","96", "ac", "74", "22", "e7", "ad", "35", "85", "e2", "f9", "37", "e8", "1c", "75", "df", "6e","47", "f1", "1a", "71", "1d", "29", "c5", "89", "6f", "b7", "62", "0e", "aa", "18", "be", "1b","fc", "56", "3e", "4b", "c6", "d2", "79", "20", "9a", "db", "c0", "fe", "78", "cd", "5a", "f4","1f", "dd", "a8", "33", "88", "07", "c7", "31", "b1", "12", "10", "59", "27", "80", "ec", "5f","60", "51", "7f", "a9", "19", "b5", "4a", "0d", "2d", "e5", "7a", "9f", "93", "c9", "9c", "ef","a0", "e0", "3b", "4d", "ae", "2a", "f5", "b0", "c8", "eb", "bb", "3c", "83", "53", "99", "61","17", "2b", "04", "7e", "ba", "77", "d6", "26", "e1", "69", "14", "63", "55", "21", "0c", "7d" };
static const string Rcon[10] = {//密钥扩展的轮常量"01000000", "02000000","04000000", "08000000","10000000", "20000000","40000000", "80000000","1b000000", "36000000" };static const string CloumM[4][4] = {//列混淆矩阵"02","03","01","01","01","02","03","01","01","01","02","03","03","01","01","02"
};
static const string InvCloumM[4][4] = {//逆列混淆矩阵"0e","0b","0d","09","09","0e","0b","0d","0d","09","0e","0b","0b","0d","09","0e"
};
static const string PiarTable[16][16]{//对数表"  ","00","19","01","32","02","1a","c6","4b","c7","1b","68","33","ee","df","03","64","04","e0","0e","34","8d","81","ef","4c","71","08","c8","f8","69","1c","c1","7d","c2","1d","b5","f9","b9","27","6a","4d","e4","a6","72","9a","c9","09","78","65","2f","8a","05","21","0f","e1","24","12","f0","82","45","35","93","da","8e","96","8f","db","bd","36","d0","ce","94","13","5c","d2","f1","40","46","83","38","66","dd","fd","30","bf","06","8b","62","b3","25","e2","98","22","88","91","10","7e","6e","48","c3","a3","b6","1e","42","3a","6b","28","54","fa","85","3d","ba","2b","79","0a","15","9b","9f","5e","ca","4e","d4","ac","e5","f3","73","a7","57","af","58","a8","50","f4","ea","d6","74","4f","ae","e9","d5","e7","e6","ad","e8","2c","d7","75","7a","eb","16","0b","f5","59","cb","5f","b0","9c","a9","51","a0","7f","0c","f6","6f","17","c4","49","ec","d8","43","1f","2d","a4","76","7b","b7","cc","bb","3e","5a","fb","60","b1","86","3b","52","a1","6c","aa","55","29","9d","97","b2","87","90","61","be","dc","fc","bc","95","cf","cd","37","3f","5b","d1","53","39","84","3c","41","a2","6d","47","14","2a","9e","5d","56","f2","d3","ab","44","11","92","d9","23","20","2e","89","b4","7c","b8","26","77","99","e3","a5","67","4a","ed","de","c5","31","fe","18","0d","63","8c","80","c0","f7","70","07"
};
static const string RservePiarTable[16][16]{//反对数表"01","03","05","0f","11","33","55","ff","1a","2e","72","96","a1","f8","13","35","5f","e1","38","48","d8","73","95","a4","f7","02","06","0a","1e","22","66","aa","e5","34","5c","e4","37","59","eb","26","6a","be","d9","70","90","ab","e6","31","53","f5","04","0c","14","3c","44","cc","4f","d1","68","b8","d3","6e","b2","cd","4c","d4","67","a9","e0","3b","4d","d7","62","a6","f1","08","18","28","78","88","83","9e","b9","d0","6b","bd","dc","7f","81","98","b3","ce","49","db","76","9a","b5","c4","57","f9","10","30","50","f0","0b","1d","27","69","bb","d6","61","a3","fe","19","2b","7d","87","92","ad","ec","2f","71","93","ae","e9","20","60","a0","fb","16","3a","4e","d2","6d","b7","c2","5d","e7","32","56","fa","15","3f","41","c3","5e","e2","3d","47","c9","40","c0","5b","ed","2c","74","9c","bf","da","75","9f","ba","d5","64","ac","ef","2a","7e","82","9d","bc","df","7a","8e","89","80","9b","b6","c1","58","e8","23","65","af","ea","25","6f","b1","c8","43","c5","54","fc","1f","21","63","a5","f4","07","09","1b","2d","77","99","b0","cb","46","ca","45","cf","4a","de","79","8b","86","91","a8","e3","3e","42","c6","51","f3","0e","12","36","5a","ee","29","7b","8d","8c","8f","8a","85","94","a7","f2","0d","17","39","4b","dd","7c","84","97","a2","fd","1c","24","6c","b4","c7","52","f6","01"};
//辅助函数
//十六进制变二进制
string AESHexToBinary(string hex)//十六进制变二进制
{string binnum = "";int n = hex.size();for (int j = 0; j < hex.length(); j++){switch (hex[j]){case '0':binnum += "0000"; break;case '1':binnum += "0001"; break;case '2':binnum += "0010"; break;case '3':binnum += "0011"; break;case '4':binnum += "0100"; break;case '5':binnum += "0101"; break;case '6':binnum += "0110"; break;case '7':binnum += "0111"; break;case '8':binnum += "1000"; break;case '9':binnum += "1001"; break;case 'A':binnum += "1010"; break;case 'B':binnum += "1011"; break;case 'C':binnum += "1100"; break;case 'D':binnum += "1101"; break;case 'E':binnum += "1110"; break;case 'F':binnum += "1111"; break;case 'a':binnum += "1010"; break;case 'b':binnum += "1011"; break;case 'c':binnum += "1100"; break;case 'd':binnum += "1101"; break;case 'e':binnum += "1110"; break;case 'f':binnum += "1111"; break;default:break;}}return binnum;
}
//二进制转十六进制
string AESBinaryToHex(string binary)//二进制转十六进制
{string hex = "";int temp;for (int i = 0; i < binary.size(); i += 4){//转化为int型temp = ((int)binary[i] - (int)'0') * 8 + ((int)binary[i + 1] - (int)'0') * 4+ ((int)binary[i + 2] - (int)'0') * 2 + ((int)binary[i + 3] - (int)'0') * 1;//cout << temp;if (temp >= 10){switch (temp){case 10:hex += "a"; break;case 11:hex += "b"; break;case 12:hex += "c"; break;case 13:hex += "d"; break;case 14:hex += "e"; break;case 15:hex += "f"; break;}}else{hex += to_string(temp);}}return hex;
}
//两个二进制字符串的异或后的十六进制
string AESXOR(string str1, string str2)//两个二进制字符串的异或后的十六进制
{string outcome = "";for (int i = 0; i < str1.size(); i++){if (str1[i] == str2[i])outcome += "0";else{outcome += "1";}}return AESBinaryToHex(outcome);
}
//输入:两个两位的16进制字符串  输出:两个两位的16进制字符串相加后的结果
string HexAdd(string hex1, string hex2)//输入:两个两位的16进制字符串  输出:两个两位的16进制字符串相加后的结果
{int jinwei = 0;int x1, x2,y1,y2;//第一个十六进制的第二位if ((int)hex1[1] < 96)//如果小于96的化,证明为数字x2 = (int)hex1[1] - (int)'0';//用Ascii码准换为整型else//证明为字符{x2 = (int)hex1[1] - (int)'a' + 10;//转化为十六进制的类型}//第一个十六进制的第一位if ((int)hex1[0] < 96)x1 = (int)hex1[0] - (int)'0';else{x1 = (int)hex1[0] - (int)'a' + 10;}//第二个十六进制的第二位if ((int)hex2[1] < 96)//,如果小于96的化,证明为数字y2 = (int)hex2[1] - (int)'0';//用Ascii码准换为整型else//证明为字符{y2 = (int)hex2[1] - (int)'a' + 10;//转化为十六进制的类型}//第二个十六进制的第一位if ((int)hex2[0] < 96)y1 = (int)hex2[0] - (int)'0';else{y1 = (int)hex2[0] - (int)'a' + 10;}//两个十六进制的第二位相加int temp2;if ((x2 + y2) >= 16)//产生进位{jinwei = 1;temp2 = (x2 + y2) % 16;}else//未产生进位{temp2 = x2 + y2;}int temp1;//两个十六进制的第一位相加if (jinwei == 1){temp1 = x1 + y1 + 1;}else{temp1 = x1 + y1;}if (temp1 >= 16)//第一位上产生进位需要摸掉ff{temp1 = temp1 % 16;temp2 += 1;//这一步很关键,在模掉ff过后,第二位是需要+1的,第一位不变}string out = "";if (temp1 < 10)out += to_string(temp1);else{out += (char)(temp1 -10+ (int)'a');}if (temp2 < 10)out += to_string(temp2);else{out += (char)(temp2-10 + (int)'a');}return out;
}
//计算列混淆中的行列乘积在异或后的值,输入:S态,S态的行数,falge表示是加密还是解密,S态的列数。输入:行列乘积在异或后的值
string MaxRowColMul(string **state,int i,int k,int flage)//计算列混淆中的行列乘积在异或后的值,输入:S态,S态的行数,falge表示是加密还是解密,S态的列数。输入:行列乘积在异或后的值
{string sum[4];for (int j = 0; j < 4; j++){string str = state[j][k];if (str == "  "){sum[j] = "00";}else{int x, y;if ((int)str[0] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)str[0] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)str[0] - (int)'a' + 10;//转化为十六进制的类型}if ((int)str[1] < 96)//处理第二个字符x = (int)str[1] - (int)'0';else{x = (int)str[1] - (int)'a' + 10;}string piar1 = PiarTable[y][x];//获取第一个数的指数if (flage == 0)//0表示加密{str = CloumM[i][j];}if (flage == 1)//1表示解密{str = InvCloumM[i][j];}if ((int)str[0] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)str[0] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)str[0] - (int)'a' + 10;//转化为十六进制的类型}if ((int)str[1] < 96)//处理第二个字符x = (int)str[1] - (int)'0';else{x = (int)str[1] - (int)'a' + 10;}string piar2 = PiarTable[y][x];//获取第二个数的指数string addout = HexAdd(piar1, piar2);//获取两个指数相加的结果if ((int)addout[0] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)addout[0] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)addout[0] - (int)'a' + 10;//转化为十六进制的类型}if ((int)addout[1] < 96)//处理第二个字符x = (int)addout[1] - (int)'0';else{x = (int)addout[1] - (int)'a' + 10;}sum[j] = RservePiarTable[y][x];}}string rox01 = AESXOR(AESHexToBinary(sum[0]), AESHexToBinary(sum[1]));string rox012 = AESXOR(AESHexToBinary(rox01), AESHexToBinary(sum[2]));string rox0123 = AESXOR(AESHexToBinary(rox012), AESHexToBinary(sum[3]));return rox0123;
}//轮密钥生成
string RotWord(string word)//输入:8个十六进制(一个字)输出:循环左移一个字节后的8个十六进制(一个字)
{//是以一个字节为单位的移动(两个十六进制)string out = "";for (int i = 2; i < 8; i++){out += word[i];}out += word[0];out += word[1];return out;
}
string SubWord(string word)//输入:循环左移后的一个字(8个十六进制)输出:替换后的一个字
{int x, y;//S盒纵坐标与横坐标的取值string out = "";//输出的结果for (int i = 0; i < word.length(); i += 2)//两两一对的对密钥进行遍历{if ((int)word[i] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)word[i] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)word[i] - (int)'a' + 10;//转化为十六进制的类型}if ((int)word[i + 1] < 96)//处理第二个字符x = (int)word[i + 1] - (int)'0';else{x = (int)word[i + 1] - (int)'a' + 10;}out += S[y][x];//把准换的值累加起来}return out;
}
string * KeyExpansion(string initialkey,int N)//输入扩展前的密钥,与加密轮数。输出:扩展后的密钥集
{int size = 4 * (N + 1);string *wkey=new string[size];for (int i = 0; i < 4; i++){wkey[i] = initialkey.substr(i*8, 8);}for (int i = 4; i < size; i++){if (i % 4 == 0){string Rotout = RotWord(wkey[i - 1]);string Subout = SubWord(Rotout);string Rconout = AESXOR(AESHexToBinary(Subout), AESHexToBinary(Rcon[i / 4-1]));string result = AESXOR(AESHexToBinary(Rconout), AESHexToBinary(wkey[i - 4]));wkey[i] = result;}else{wkey[i] = AESXOR(AESHexToBinary(wkey[i - 1]), AESHexToBinary(wkey[i - 4]));}}return wkey;
}
//加密所用函数
string** PlantTextToState(string hexstring)//输入:32个十六进制(16字节,128bit)。输出:二维字符数组
{string state[4][4];int k = 0;for (int i = 0; i < 4; i++)//从左到右从上到下{for (int j = 0; j < 4; j++){state[j][i] = hexstring.substr(k, 2);k += 2;}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = state[i][j];return ps;  //返回的是动态数组的地址,不会被释放,需要在调用者(此处为main)中主动释放次函数中动态分配的内存
}
string** AddRoundKey(string** state, string* wkey, int n)//输入:中间态state,轮密钥,第几轮加密,输出:加密后新状态ps
{string temp[4][4];int k = 0;for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){temp[j][i] = AESXOR(AESHexToBinary(state[j][i]), AESHexToBinary( wkey[4 * n + i].substr(k, 2)));//输出态的行列值与四轮一组的密钥的相应值进行异或k += 2;}k =0;}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;  //返回的是动态数组的地址,不会被释放,需要在调用者(此处为main)中主动释放次函数中动态分配的内存
}
string** SubBytes(string** state)//输入:中间态state  输出:新的中间态state
{string temp[4][4];for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){string str = state[i][j];int x, y;if ((int)str[0] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)str[0] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)str[0] - (int)'a' + 10;//转化为十六进制的类型}if ((int)str[1] < 96)//处理第二个字符x = (int)str[1] - (int)'0';else{x = (int)str[1] - (int)'a' + 10;}temp[i][j] = S[y][x];}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;  //返回的是动态数组的地址,不会被释放,需要在调用者(此处为main)中主动释放次函数中动态分配的内存
}
string** MixColumns(string** state)
{string temp[4][4];for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){temp[i][j] = MaxRowColMul(state, i, j,0);//获取矩阵乘法的值}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;
}
string** ShiftRows(string** state)
{string temp[4][4];for (int i = 0; i < 4; i++){if(i==0)for (int j = 0; j <4; j++){temp[i][j] = state[i][j];}if (i == 1){for (int j = 0; j < 3; j++){temp[i][j] = state[i][j + 1];temp[i][3] = state[i][0];}}if (i == 2){for (int j = 0; j < 2; j++){temp[i][j] = state[i][j + 2];temp[i][j + 2] = state[i][j];}}if (i == 3){for (int j = 1; j < 4; j++){temp[i][j] = state[i][j - 1];temp[i][0] = state[i][3];}}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;
}
//解密所用函数
string** InvSubBytes(string** state)//输入:中间态state  输出:新的中间态state
{string temp[4][4];for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){string str = state[i][j];int x, y;if ((int)str[0] < 96)//第一个为纵坐标的值,如果小于96的化,证明为数字y = (int)str[0] - (int)'0';//用Ascii码准换为整型else//证明为字符{y = (int)str[0] - (int)'a' + 10;//转化为十六进制的类型}if ((int)str[1] < 96)//处理第二个字符x = (int)str[1] - (int)'0';else{x = (int)str[1] - (int)'a' + 10;}temp[i][j] = InvS[y][x];}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;  //返回的是动态数组的地址,不会被释放,需要在调用者(此处为main)中主动释放次函数中动态分配的内存
}
string** InvShiftRows(string** state)
{string temp[4][4];for (int i = 0; i < 4; i++){if (i == 0)for (int j = 0; j < 4; j++){temp[i][j] = state[i][j];}if (i == 1){for (int j = 0; j < 3; j++){temp[i][j+1] = state[i][j];temp[i][0] = state[i][3];}}if (i == 2){for (int j = 0; j < 2; j++){temp[i][j+2] = state[i][j];temp[i][j] = state[i][j+2];}}if (i == 3){for (int j = 1; j < 4; j++){temp[i][j-1] = state[i][j];temp[i][3] = state[i][0];}}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;
}
string** InvMixColumns(string** state)
{string temp[4][4];for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){temp[i][j] = MaxRowColMul(state, i, j,1);//获取矩阵乘法的值}}string** ps = new string * [4];   //动态指针数组for (int i = 0; i < 4; i++)ps[i] = new string[4];//每个指针又指向一个一维字符串数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)ps[i][j] = temp[i][j];return ps;
}
//加解密
string AESEncryption(string plantxt,string key,int n)
{string* wkey= KeyExpansion(key, n);//先进行密钥扩展string** state = PlantTextToState(plantxt);//把明文变成S态state = AddRoundKey(state, wkey, 0);//先对明文进行一次轮密钥加for (int i = 0; i < 9; i++)//进行九轮循环操作{state = SubBytes(state);state = ShiftRows(state);state = MixColumns(state);state = AddRoundKey(state, wkey,i+1);     }state = SubBytes(state);//最后一轮没有列混淆state = ShiftRows(state);state = AddRoundKey(state, wkey, 10);string out = "";//输出密文for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){out += state[j][i];}}for (int i = 0; i < 4; i++)   //释放函数f 里动态分配的内存delete[] state[i];delete[]state;return out;
}
string AESDecryption(string ciphertext, string key, int n)
{string* wkey = KeyExpansion(key, n);//先进行密钥扩展string** state = PlantTextToState(ciphertext);//把密文变成S态state = AddRoundKey(state, wkey, 10);//先对密文进行一次轮密钥加for (int i = 9; i >0; i--)//进行九轮循环操作{state = InvShiftRows(state);state = InvSubBytes(state);state = AddRoundKey(state, wkey, i);state = InvMixColumns(state);}state = InvShiftRows(state);state = InvSubBytes(state);//最后一轮没有列混淆state = AddRoundKey(state, wkey, 0);string out = "";//输出明文for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){out += state[j][i];}}for (int i = 0; i < 4; i++)   //释放函数f 里动态分配的内存delete[] state[i];delete[]state;return out;
}
//加解密测试
void AESEncryptionTest()
{string plantxt = "3243f6a8885a308d313198a2e0370734";string key = "2b7e151628aed2a6abf7158809cf4f3c";cout << "加密原文128bit:" << plantxt<<endl;cout << "密钥128bit:" << key << endl;clock_t starttime, endtime;starttime = clock();cout << "加密结果128bit:"<<AESEncryption(plantxt, key, 10);endtime = clock();cout << endl << "AES加密所用的时间为:" << (double)(endtime - starttime) / CLOCKS_PER_SEC << "s" << endl;
}
void AESDecryptionTest()
{string ciphertext = "3925841d02dc09fbdc118597196a0b32";string key = "2b7e151628aed2a6abf7158809cf4f3c";cout << "解密原文128bit:" << ciphertext << endl;cout << "密钥128bit:" << key << endl;clock_t starttime, endtime;starttime = clock();cout << "解密结果128bit:" << AESDecryption(ciphertext, key, 10);endtime = clock();cout << endl << "AES解密所用的时间为:" << (double)(endtime - starttime) / CLOCKS_PER_SEC << "s" << endl;
}

AES(128bit十六进制的加密)相关推荐

  1. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写"一套简单的web即时通讯",写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSo ...

  2. aes 加密_结合RSA与AES实现前后端加密通信

    结合RSA与AES实现前后端加密通信 一.思路 使用RSA秘钥生成工具生成一对公钥(A)和私钥(B),前端保留A,后端保留B. 前端发送数据时,先生成一串随机16位字符串作为AES的秘钥(C),然后使 ...

  3. golang实现AES ECB模式的加密和解密

    最近有一个需求需要在golang中实现AES ECB模式的加密和解密,  看了一下官方文档和相关资料发现golang 官方包并没有完善的实现,于是自己尝试写了一个,本文中的AES算法是基于ECB模式, ...

  4. AES与RSA混合加密完整实例

    前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用RSA来 ...

  5. 【加密】对称加密DES和非对称加密AES、数字签名|非对称加密--公钥和私钥的区别

    目录 对称加密DES和非对称加密AES.数字签名 对称加密 1.1 定义 1.2 优缺点 1.3 常用对称加密算法 非对称加密( Asymmetric Cryptography ) 非对称加密(现代加 ...

  6. python AES中EBC模式加密

    **from Crypto.Cipher import AES import base64 # 来自微信好友:一觉昏睡人 BLOCK_SIZE = 16 # Bytes pad = lambda s: ...

  7. AES 128位CBC加密解密(不使用固定IV)

    安全检查时要求账号和密码加密后才能存到数据库中,要求加密算法如下: 1)分组密码算法:AES(密钥长度在128位及以上)(GCM或CBC模式) 2)流密码算法:AES(密钥长度在128位及以上)(OF ...

  8. VB AES 字符串和文件加密

    此代码在源码天空等多个源码站点上可以下载本人仅做了简单的修改总结为4个函数进行调用 1.EncryptStr/加密字符串 2.DecryptStr/解密字符串 3.EncryptFile/加密文件 4 ...

  9. ecb gcm java 加密,AES GCM和ECB加密软件,附算法源码和工程文件

    [实例简介] AesTestTool为加密软件,支持GCM 和 ECB两种模式 128bit秘钥 GCM算法是一个C++工程,"C++gcm算法工程"目录里面有源码 加密软件是用C ...

最新文章

  1. c#程序设定使用期限_C# 给某个方法设定执行超时时间
  2. 两个nb模块之间通讯方法_NB-IoT是什么?一口气带你搞懂NB-IoT的诞生、特性以及应用...
  3. vb制作可输出函数的通用DLL---VB_DLL_Link用法
  4. Linux教程:内核怎样管理你的内存
  5. linux驱动程序混合架构,嵌入式系统最小驱动框架(类似linux驱动程序架构)(示例代码)...
  6. 二叉树前序遍历、中序遍历、后序遍历手稿
  7. 提交表单到弹出窗口 Submit a form into a popup
  8. 利用VBS合并Excel中相同单元格
  9. Linux下Nodejs安装
  10. android里面的广播,Android里面的各种广播
  11. 支持了Unicode及各国字符集编码识别]改善IDA6.8对中文等非英语国家的ANSI字符串显示支持不佳的问题...
  12. 王道考研操作系统笔记(第一章)附:王道考研408所有PPT和思维导图
  13. 三极管放大电路的基本原理
  14. 表单的 9 种设计技巧【上】
  15. O(nlogn) 求LIS(Longest Increasing Subsequence)方法的总结
  16. 指南解读:急性心力衰竭中国急诊管理指南(2022)
  17. 智能交通系统功能模块
  18. dos模拟器即时存档工具_安卓dos模拟器下载-dos模拟器中文版下载v1.0.60 安卓版-2265手游网...
  19. 如何提出保存PDF指定的几页
  20. 你真的知道什么是 JDK吗?

热门文章

  1. 使用python异步爬取淘宝大量商品的价格,并生成excel文件
  2. Vue脚手架使用【快速入门】
  3. java 逻辑运算符的概念和使用
  4. 原油价格涨幅与什么有关
  5. redis 发布订阅示例
  6. Activiti5学习笔记(二)
  7. 中式红木整装,打造专属红木工艺的中式高定空间
  8. html显示隐藏域的值,JavaScript获取文本框/编辑框/隐藏域的值
  9. Nand Flash调试日志(1)——时钟频率配置
  10. php 检测服务器网速_PHP探针推荐:检测服务器环境好帮手