AES(128bit十六进制的加密)

在写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;
}

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

remandancy.h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值