AES详细加解密步骤以及AES-128的C++实现


本文详细阐述了AES-128的基本加解密步骤,AES-192与AES-256加解密方式与AES-128一样,只是AES-128运算10轮,AES-192与AES-256分别运算12轮和14轮。

文中用到的示例:

明文:32 43 F6 A8 88 5A 30 8D 31 31 98 A2 E0 37 07 34
密钥:2B 7E 15 16 28 AE D2 A6 AB F7 15 88 09 CF 4F 3C
密文:39 25 84 1D 02 DC 09 FB DC 11 85 97 19 6A 0B 32

用到的矩阵

S盒

/****    0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f */
		/*0*/{
    
     "63", "7C", "77", "7B", "F2", "6B", "6F", "C5", "30", "01", "67", "2B", "FE", "D7", "AB", "76" },
		/*1*/{
    
     "CA", "82", "C9", "7D", "FA", "59", "47", "F0", "AD", "D4", "A2", "AF", "9C", "A4", "72", "C0" },
		/*2*/{
    
     "B7", "FD", "93", "26", "36", "3F", "F7", "CC", "34", "A5", "E5", "F1", "71", "D8", "31", "15" },
		/*3*/{
    
     "04", "C7", "23", "C3", "18", "96", "05", "9A", "07", "12", "80", "E2", "EB", "27", "B2", "75" },
		/*4*/{
    
     "09", "83", "2C", "1A", "1B", "6E", "5A", "A0", "52", "3B", "D6", "B3", "29", "E3", "2F", "84" },
		/*5*/{
    
     "53", "D1", "00", "ED", "20", "FC", "B1", "5B", "6A", "CB", "BE", "39", "4A", "4C", "58", "CF" },
		/*6*/{
    
     "D0", "EF", "AA", "FB", "43", "4D", "33", "85", "45", "F9", "02", "7F", "50", "3C", "9F", "A8" },
		/*7*/{
    
     "51", "A3", "40", "8F", "92", "9D", "38", "F5", "BC", "B6", "DA", "21", "10", "FF", "F3", "D2" },
		/*8*/{
    
     "CD", "0C", "13", "EC", "5F", "97", "44", "17", "C4", "A7", "7E", "3D", "64", "5D", "19", "73" },
		/*9*/{
    
     "60", "81", "4F", "DC", "22", "2A", "90", "88", "46", "EE", "B8", "14", "DE", "5E", "0B", "DB" },
		/*a*/{
    
     "E0", "32", "3A", "0A", "49", "06", "24", "5C", "C2", "D3", "AC", "62", "91", "95", "E4", "79" },
		/*b*/{
    
     "E7", "C8", "37", "6D", "8D", "D5", "4E", "A9", "6C", "56", "F4", "EA", "65", "7A", "AE", "08" },
		/*c*/{
    
     "BA", "78", "25", "2E", "1C", "A6", "B4", "C6", "E8", "DD", "74", "1F", "4B", "BD", "8B", "8A" },
		/*d*/{
    
     "70", "3E", "B5", "66", "48", "03", "F6", "0E", "61", "35", "57", "B9", "86", "C1", "1D", "9E" },
		/*e*/{
    
     "E1", "F8", "98", "11", "69", "D9", "8E", "94", "9B", "1E", "87", "E9", "CE", "55", "28", "DF" },
		/*f*/{
    
     "8C", "A1", "89", "0D", "BF", "E6", "42", "68", "41", "99", "2D", "0F", "B0", "54", "BB", "16" }

S盒的逆

/****   0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f */
		/*0*/{
    
    "52", "09", "6A", "D5", "30", "36", "A5", "38", "BF", "40", "A3", "9E", "81", "F3", "D7", "FB"},
		/*1*/{
    
    "7C", "E3", "39", "82", "9B", "2F", "FF", "87", "34", "8E", "43", "44", "C4", "DE", "E9", "CB"},
		/*2*/{
    
    "54", "7B", "94", "32", "A6", "C2", "23", "3D", "EE", "4C", "95", "0B", "42", "FA", "C3", "4E"},
		/*3*/{
    
    "08", "2E", "A1", "66", "28", "D9", "24", "B2", "76", "5B", "A2", "49", "6D", "8B", "D1", "25"},
		/*4*/{
    
    "72", "F8", "F6", "64", "86", "68", "98", "16", "D4", "A4", "5C", "CC", "5D", "65", "B6", "92"},
		/*5*/{
    
    "6C", "70", "48", "50", "FD", "ED", "B9", "DA", "5E", "15", "46", "57", "A7", "8D", "9D", "84"},
		/*6*/{
    
    "90", "D8", "AB", "00", "8C", "BC", "D3", "0A", "F7", "E4", "58", "05", "B8", "B3", "45", "06"},
		/*7*/{
    
    "D0", "2C", "1E", "8F", "CA", "3F", "0F", "02", "C1", "AF", "BD", "03", "01", "13", "8A", "6B"},
		/*8*/{
    
    "3A", "91", "11", "41", "4F", "67", "DC", "EA", "97", "F2", "CF", "CE", "F0", "B4", "E6", "73"},
		/*9*/{
    
    "96", "AC", "74", "22", "E7", "AD", "35", "85", "E2", "F9", "37", "E8", "1C", "75", "DF", "6E"},
		/*a*/{
    
    "47", "F1", "1A", "71", "1D", "29", "C5", "89", "6F", "B7", "62", "0E", "AA", "18", "BE", "1B"},
		/*b*/{
    
    "FC", "56", "3E", "4B", "C6", "D2", "79", "20", "9A", "DB", "C0", "FE", "78", "CD", "5A", "F4"},
		/*c*/{
    
    "1F", "DD", "A8", "33", "88", "07", "C7", "31", "B1", "12", "10", "59", "27", "80", "EC", "5F"},
		/*d*/{
    
    "60", "51", "7F", "A9", "19", "B5", "4A", "0D", "2D", "E5", "7A", "9F", "93", "C9", "9C", "EF"},
		/*e*/{
    
    "A0", "E0", "3B", "4D", "AE", "2A", "F5", "B0", "C8", "EB", "BB", "3C", "83", "53", "99", "61"},
		/*f*/{
    
    "17", "2B", "04", "7E", "BA", "77", "D6", "26", "E1", "69", "14", "63", "55", "21", "0C", "7D"}

轮常量矩阵

	{
    
    "01", "00", "00", "00"},
	{
    
    "02", "00", "00", "00"},
	{
    
    "04", "00", "00", "00"},
	{
    
    "08", "00", "00", "00"},
	{
    
    "10", "00", "00", "00"},
	{
    
    "20", "00", "00", "00"},
	{
    
    "40", "00", "00", "00"},
	{
    
    "80", "00", "00", "00"},
	{
    
    "1B", "00", "00", "00"},
	{
    
    "36", "00", "00", "00"}

列混合矩阵

列混合矩阵

列混合矩阵的逆

列混合矩阵的逆

加密步骤

对密钥的处理(密钥扩展)

将密钥K按列优先读取到一个4×4的矩阵中,然后按列分组,将前四列分别命名为k[0] - k[3],然后向后扩展k[4]、k[5]直至k[43],接下来就是计算扩展密钥:当k[i]的i不是4的倍数的时候,k[i] = k[i - 1]⨁k[i - 1],如果i是4的倍数,则需要先将k[i - 1]列进行一轮字循环,然后进行字节替代,得到的结果与k[i - 1]和轮常量矩阵相应轮数的那一列进行抑或,得到的结果就是k[i],如此反复,得到一个4×44的扩展秘钥矩阵,然后按照4×4一组,划分为K0 - K10共11个矩阵,加密解密均用此矩阵。
例如:前文所述的密钥读到矩阵(K0)之中为:

k[0] k[1] k[2] k[3]
2B 28 AB 09
7E AE F7 CF
15 D2 15 4F
16 A6 88 3C

i为4的倍数以k[4]为例:
由于4是4的倍数,因此计算较麻烦,k[i-1]是k[3]为{09,CF,4F,3C},左移一位,结果为{CF,4F,3C,09} 1 ◯ \textcircled{1} 1,然后根据S盒进行变换得到{8A,84,EB,01} 2 ◯ \textcircled{2} 2,最后取轮常量矩阵的第i%4=1列{01,00,00,00} 3 ◯ \textcircled{3} 3,将 1 ◯ \textcircled{1} 1 2 ◯ \textcircled{2} 2 3 ◯ \textcircled{3} 3抑或得到k[4] = {A0,FA,FE,17}。k[8]、k[12]等等k[4i]同理

i不是4的倍数以k[5]为例:
完整的密钥矩阵为:由于5不是4的倍数,因此直接计算k[i-1] + ◯ \textcircled{+} +k[i-4],即{A0,FA,FE,17} + ◯ \textcircled{+} +{28,AE,D2,A6} = {88,54,2C,B1},其他的同理。

最终得到的扩展密钥矩阵如下:

k[0] k[1] k[2] k[3] k[4] k[5] k[6] k[7] k[8] k[9] k[10] k[11] k[12] k[13] k[14] k[15] k[16] k[17] k[18] k[19] k[20] k[21] k[22] k[23] k[24] k[25] k[26] k[27] k[28] k[29] k[30] k[31] k[32] k[33] k[34] k[35] k[36] k[37] k[38] k[39] k[40] k[41] k[42] k[43]
2B 28 AB 09 A0 88 23 2A F2 7A 59 73 3D 47 1E 6D EF A8 B6 DB D4 7C CA 11 6D 11 DB CA 4E 5F 84 4E EA B5 31 7F AC 19 28 57 D0 C9 E1 B6
7E AE F7 CF FA 54 A3 6C C2 96 35 59 80 16 23 7A 44 52 71 0B D1 83 F2 F9 88 0B F9 00 54 5F A6 A6 D2 8D 2B 8D 77 FA D1 5C 14 EE 3F 63
15 D2 15 4F FE 2C 39 76 95 B9 80 F6 47 FE 7E 88 A5 5B 25 AD C6 9D B8 15 A3 3E 86 93 F7 C9 4F DC 73 BA F5 29 66 DC 29 00 F9 25 0C 0C
16 A6 88 3C 17 B1 39 05 F2 43 7A 7F 7D 3E 44 3B 41 7F 3B 00 F8 87 BC BC 7A FD 41 FD 0E F3 B2 4F 21 D2 60 2F F3 21 41 6E A8 89 C8 A6

其中K0为k[0]-k[3],K1为k[4]-k[7],以此类推

扫描二维码关注公众号,回复: 14588924 查看本文章

对明文的处理

首先将明文按列优先保存至4×4的矩阵P中,然后进行初始变换,然后进行9轮循环运算,最后进行一轮最终轮运算之后得到密文。
初始变换:将明文矩阵与K0整体进行抑或(解密过程为与K10抑或)
在这里插入图片描述
例如:将明文读入到矩阵中:

32 88 31 E0
43 5A 31 37
F6 30 98 07
A8 8D A2 34

初始变换的结果为P + ◯ \textcircled{+} +K0

19 A0 9A E9
3D F4 C6 F8
E3 E2 8D 48
BE 2B 2A 08

9轮循环运算:加密过程中为:按顺序进行字节代换、行移位、列混合以及轮密钥加
解密过程中为:按顺序进行列混合、行移位、字节替换以及轮密钥加
最终轮运算:加密过程中为:按顺序进行字节代换、行移位以及轮密钥加
解密过程中为:按顺序进行行移位,字节代换以及轮密钥加

字节替换

对输入矩阵的每一字中的两位,第一位作为行号,第二位作为列号,到S盒(加密用S盒,解密用S盒的逆)中寻找相应的字并替换成新的。
例如:在加密的第一轮过程中,输入的矩阵第一个字为“19”,到S盒中寻找行号为1,列号为9的的字为D4,因此将19替换为D4,第一轮替换的结果为:
在这里插入图片描述

行移位

加密过程中,将第输入矩阵的第2,3,4行分别左移1,2,3位,解密过程中改为右移。
例如:加密第一轮过程中行移位之后的结果为:
在这里插入图片描述

GF(28)上的乘法

A = a0a1a2a3a4a5a6a7a8
01×A = A
02×A:若a0=0,直接左移一位,右侧补0,即 =a1a2a3a4a5a6a7a80
若a0≠0,则左移一位右侧补0后与1B(00011011)抑或
其他乘法可由以上两式推导出来,譬如03(00000011)×A即为(01(00000001) + ◯ \textcircled{+} + 02(00000010)) ×A = (01×A) + ◯ \textcircled{+} + (02×A),04(00000100) = 02×02,09(00001001) = 08 + ◯ \textcircled{+} + 01,0B(00001011)=08 + ◯ \textcircled{+} + 02 + ◯ \textcircled{+} + 01,以此类推

列混合

将输入的矩阵左乘列混合矩阵(解密过程中为左乘列混合矩阵的逆),运算过程中乘法为GF(28)上的乘法,加法为按位异或
例如,第一轮加密过程中列混合后的矩阵为:
在这里插入图片描述

轮密钥加

第i轮就将输入矩阵与Ki矩阵逐字抑或(加解密一样)
例如:加密过程中第一轮,输入矩阵为:
在这里插入图片描述
K1为:
在这里插入图片描述
抑或结果为:

在这里插入图片描述
第二轮至第十轮的运算结果分别为:
在这里插入图片描述
在这里插入图片描述

解密步骤

将密文按列优先读进4×4矩阵,然后进行初始变换,然后进行一轮最终轮运算,最后进行9轮循环运算之后得到密文。

代码实现

源代码

/******************************************************************************************
 * Name: AES.cpp
 * Author: kongtaoxing
 * Time: 2022/10/08
 * Tips: All algebraic operations in this project are performed in the GF(2^8) finite field
 ******************************************************************************************/

#include<string>
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

char Sbox[16][16][3] = {
    
    
	    /****    0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f */
		/*0*/{
    
     "63", "7C", "77", "7B", "F2", "6B", "6F", "C5", "30", "01", "67", "2B", "FE", "D7", "AB", "76" },
		/*1*/{
    
     "CA", "82", "C9", "7D", "FA", "59", "47", "F0", "AD", "D4", "A2", "AF", "9C", "A4", "72", "C0" },
		/*2*/{
    
     "B7", "FD", "93", "26", "36", "3F", "F7", "CC", "34", "A5", "E5", "F1", "71", "D8", "31", "15" },
		/*3*/{
    
     "04", "C7", "23", "C3", "18", "96", "05", "9A", "07", "12", "80", "E2", "EB", "27", "B2", "75" },
		/*4*/{
    
     "09", "83", "2C", "1A", "1B", "6E", "5A", "A0", "52", "3B", "D6", "B3", "29", "E3", "2F", "84" },
		/*5*/{
    
     "53", "D1", "00", "ED", "20", "FC", "B1", "5B", "6A", "CB", "BE", "39", "4A", "4C", "58", "CF" },
		/*6*/{
    
     "D0", "EF", "AA", "FB", "43", "4D", "33", "85", "45", "F9", "02", "7F", "50", "3C", "9F", "A8" },
		/*7*/{
    
     "51", "A3", "40", "8F", "92", "9D", "38", "F5", "BC", "B6", "DA", "21", "10", "FF", "F3", "D2" },
		/*8*/{
    
     "CD", "0C", "13", "EC", "5F", "97", "44", "17", "C4", "A7", "7E", "3D", "64", "5D", "19", "73" },
		/*9*/{
    
     "60", "81", "4F", "DC", "22", "2A", "90", "88", "46", "EE", "B8", "14", "DE", "5E", "0B", "DB" },
		/*a*/{
    
     "E0", "32", "3A", "0A", "49", "06", "24", "5C", "C2", "D3", "AC", "62", "91", "95", "E4", "79" },
		/*b*/{
    
     "E7", "C8", "37", "6D", "8D", "D5", "4E", "A9", "6C", "56", "F4", "EA", "65", "7A", "AE", "08" },
		/*c*/{
    
     "BA", "78", "25", "2E", "1C", "A6", "B4", "C6", "E8", "DD", "74", "1F", "4B", "BD", "8B", "8A" },
		/*d*/{
    
     "70", "3E", "B5", "66", "48", "03", "F6", "0E", "61", "35", "57", "B9", "86", "C1", "1D", "9E" },
		/*e*/{
    
     "E1", "F8", "98", "11", "69", "D9", "8E", "94", "9B", "1E", "87", "E9", "CE", "55", "28", "DF" },
		/*f*/{
    
     "8C", "A1", "89", "0D", "BF", "E6", "42", "68", "41", "99", "2D", "0F", "B0", "54", "BB", "16" }
	};// S盒
    
char Sboxni[16][16][3] = {
    
    
		/****   0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f */
		/*0*/{
    
    "52", "09", "6A", "D5", "30", "36", "A5", "38", "BF", "40", "A3", "9E", "81", "F3", "D7", "FB"},
		/*1*/{
    
    "7C", "E3", "39", "82", "9B", "2F", "FF", "87", "34", "8E", "43", "44", "C4", "DE", "E9", "CB"},
		/*2*/{
    
    "54", "7B", "94", "32", "A6", "C2", "23", "3D", "EE", "4C", "95", "0B", "42", "FA", "C3", "4E"},
		/*3*/{
    
    "08", "2E", "A1", "66", "28", "D9", "24", "B2", "76", "5B", "A2", "49", "6D", "8B", "D1", "25"},
		/*4*/{
    
    "72", "F8", "F6", "64", "86", "68", "98", "16", "D4", "A4", "5C", "CC", "5D", "65", "B6", "92"},
		/*5*/{
    
    "6C", "70", "48", "50", "FD", "ED", "B9", "DA", "5E", "15", "46", "57", "A7", "8D", "9D", "84"},
		/*6*/{
    
    "90", "D8", "AB", "00", "8C", "BC", "D3", "0A", "F7", "E4", "58", "05", "B8", "B3", "45", "06"},
		/*7*/{
    
    "D0", "2C", "1E", "8F", "CA", "3F", "0F", "02", "C1", "AF", "BD", "03", "01", "13", "8A", "6B"},
		/*8*/{
    
    "3A", "91", "11", "41", "4F", "67", "DC", "EA", "97", "F2", "CF", "CE", "F0", "B4", "E6", "73"},
		/*9*/{
    
    "96", "AC", "74", "22", "E7", "AD", "35", "85", "E2", "F9", "37", "E8", "1C", "75", "DF", "6E"},
		/*a*/{
    
    "47", "F1", "1A", "71", "1D", "29", "C5", "89", "6F", "B7", "62", "0E", "AA", "18", "BE", "1B"},
		/*b*/{
    
    "FC", "56", "3E", "4B", "C6", "D2", "79", "20", "9A", "DB", "C0", "FE", "78", "CD", "5A", "F4"},
		/*c*/{
    
    "1F", "DD", "A8", "33", "88", "07", "C7", "31", "B1", "12", "10", "59", "27", "80", "EC", "5F"},
		/*d*/{
    
    "60", "51", "7F", "A9", "19", "B5", "4A", "0D", "2D", "E5", "7A", "9F", "93", "C9", "9C", "EF"},
		/*e*/{
    
    "A0", "E0", "3B", "4D", "AE", "2A", "F5", "B0", "C8", "EB", "BB", "3C", "83", "53", "99", "61"},
		/*f*/{
    
    "17", "2B", "04", "7E", "BA", "77", "D6", "26", "E1", "69", "14", "63", "55", "21", "0C", "7D"}
	};	// S盒的逆

char Rcon[10][4][3] = {
    
    
	{
    
    "01", "00", "00", "00"},
	{
    
    "02", "00", "00", "00"},
	{
    
    "04", "00", "00", "00"},
	{
    
    "08", "00", "00", "00"},
	{
    
    "10", "00", "00", "00"},
	{
    
    "20", "00", "00", "00"},
	{
    
    "40", "00", "00", "00"},
	{
    
    "80", "00", "00", "00"},
	{
    
    "1B", "00", "00", "00"},
	{
    
    "36", "00", "00", "00"}
};  // 轮常量矩阵

static int flag_e = 00; //加密循环轮数
static int flag_d = 10; //解密循环轮数

vector<string> MixC = {
    
    "02", "01", "01", "03"};
vector<string> MixCni = {
    
    "0E", "09", "0D", "0B"};

string encrypt(string p, string k);
string decrypt(string c, string k);
string LowToUpper(string low);  //小写字母转大写字母
string HextoBin(string Hex);  //十六进制转二进制
string BintoHex(string Bin);  //二进制转十六进制
int HexToDec(char Hex);   //十六进制字符转10进制数字
vector<vector<string>> nineRounds(vector<vector<string>> P, vector<vector<string>> K, char ed);   //9轮变换
vector<vector<string>> finalRounds(vector<vector<string>> P, vector<vector<string>> K, char ed);   //最终轮变换
vector<vector<string>> subBytes(vector<vector<string>> P, char ed); // 字节代换
vector<vector<string>> ShiftRows(vector<vector<string>> P);   // 行移位
vector<vector<string>> invShiftRows(vector<vector<string>> P);   // 逆行移位
vector<vector<string>> MixColumns(vector<vector<string>> p, vector<string> MisC);   //列混合
vector<vector<string>> AddRoundKey(vector<vector<string>> P, vector<vector<string>> K, char ed);  //轮密钥加
vector<vector<string>> subKey(vector<vector<string>> k);  //密钥扩展
string hexXor(string a, string b); //16进制抑或
string hexTimes(string a, string b);  //16进制乘法,a为列混合矩阵元素,只取01,02,03
vector<vector<string>> transMatrix(vector<vector<string>> K);   // 转置矩阵

string encrypt(string p, string k) {
    
    
	vector<vector<string>> P(4, vector<string>(4, "00"));
	vector<vector<string>> Key(44, vector<string>(4, "00"));
	string ans = "";
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			for(int kk = 0; kk < 2; kk++) {
    
    
				P[i][j][kk] = p[(i * 4 + j) * 3 + kk];   //丢弃掉中间的空格,将字符串转换为矩阵
			}
		}
	}
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			for(int kk = 0; kk < 2; kk++) {
    
    
				Key[i][j][kk] = k[(i * 4 + j) * 3 + kk];   //丢弃掉中间的空格,将字符串转换为矩阵
			}
		}
	}
	Key = subKey(Key);
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			P[i][j] = hexXor(P[i][j], Key[i][j]);   //初始变换(Initial round)
		}
	}
	P = transMatrix(P);   // 明文矩阵是竖着读进去的,但是需要横着用
	P = nineRounds(P, Key, 'e');   //9轮循环运算
	P = finalRounds(P, Key, 'e');  //最终轮运算
	P = transMatrix(P);  //还原回去
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			ans += P[i][j];
			ans += " ";
		}
	}
	return ans;    // 得到密文
}

string decrypt(string c, string k) {
    
    
	vector<vector<string>> C(4, vector<string>(4, "00"));
	vector<vector<string>> Key(44, vector<string>(4, "00"));
	string ans = "";
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			for(int kk = 0; kk < 2; kk++) {
    
    
				C[i][j][kk] = c[(i * 4 + j) * 3 + kk];   //丢弃掉中间的空格,将字符串转换为矩阵
			}
		}
	}
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			for(int kk = 0; kk < 2; kk++) {
    
    
				Key[i][j][kk] = k[(i * 4 + j) * 3 + kk];   //丢弃掉中间的空格,将字符串转换为矩阵
			}
		}
	}
	Key = subKey(Key);
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			C[i][j] = hexXor(C[i][j], Key[40 + i][j]);   //逆初始变换(Initial round)
		}
	}
	C = transMatrix(C);   // 密文矩阵是竖着读进去的,但是需要横着用
	C = finalRounds(C, Key, 'd');  //最终轮运算
	C = nineRounds(C, Key, 'd');   //9轮循环运算
	C = transMatrix(C); //还原回去
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			ans += C[i][j];
			ans += " ";
		}
	}
	return ans;    // 得到密文
}

vector<vector<string>> subKey(vector<vector<string>> K) {
    
      //密钥扩展
	vector<vector<string>> sKey(44, vector<string>(4, "00"));
	for (int i = 0; i < 4; i++) {
    
    
		for (int j = 0; j < 4; j++) {
    
    
			sKey[i][j] = K[i][j];
		}
	}
	for (int i = 4; i < 44; i++) {
    
    
		if (i % 4 != 0) {
    
    
			for (int j = 0; j < 4; j++) {
    
    
				sKey[i][j] = hexXor(sKey[i - 4][j], sKey[i - 1][j]);
			}
		}
		else {
    
    
			vector<string> tempK = sKey[i - 1];  //字循环
			string temp = tempK[0];
			for (int j = 0; j < 3; j++) {
    
    
				tempK[j] = tempK[j + 1];
			}
			tempK[3] = temp;
			vector<string> SK = tempK;           //S盒
			for (int j = 0; j < 4; j++) {
    
    
				SK[j] = Sbox[HexToDec(tempK[j][0])][HexToDec(tempK[j][1])];
				sKey[i][j] = hexXor(hexXor(sKey[i - 4][j], SK[j]), Rcon[i / 4 - 1][j]);
			}
		}
	}
	return sKey;
}

vector<vector<string>> subBytes(vector<vector<string>> P, char ed) {
    
     // 字节代换
	vector<vector<string>> SP(4, vector<string>(4, "00"));
	if (ed == 'e') {
    
    
		for (int i = 0; i < 4; i++) {
    
    
			for (int j = 0; j < 4; j++) {
    
    
				SP[i][j] = Sbox[HexToDec(P[i][j][0])][HexToDec(P[i][j][1])];  //字节代换(SubBytes)
			}
		}
	}
	else {
    
    
		for (int i = 0; i < 4; i++) {
    
    
			for (int j = 0; j < 4; j++) {
    
    
				SP[i][j] = Sboxni[HexToDec(P[i][j][0])][HexToDec(P[i][j][1])];  //字节代换(SubBytes)
		}
		}
	}
	return SP;
}

vector<vector<string>> ShiftRows(vector<vector<string>> P) {
    
      // 行移位(ShiftRows)
	for (int i = 1; i < 4; i++) {
    
    
		vector<string> temp;
		for (int j = 0; j < i; j++) {
    
    
			temp.push_back(P[i][j]);
		}
		for (int j = i; j < 4; j++) {
    
    
			P[i][j - i] = P[i][j];
		}
		for (int j = 4 - i; j < 4; j++) {
    
    
			P[i][j] = temp[j - (4 - i)];
		}
	}
	return P;
}

vector<vector<string>> invShiftRows(vector<vector<string>> P) {
    
       // 逆行移位
	for (int i = 1; i < 4; i++) {
    
    
		vector<string> temp;
		for (int j = 4 - i; j < 4; j++) {
    
    
			temp.push_back(P[i][j]);
		}
		for (int j = 3; j >= i; j--) {
    
    
			P[i][j] = P[i][j - i];
		}
		for (int j = 0; j < i; j++) {
    
    
			P[i][j] = temp[j];
		}
	}
	return P;
}

vector<vector<string>> MixColumns(vector<vector<string>> p, vector<string> A) {
    
       //列混合
	p = transMatrix(p);  //将列转化为行,方便计算
	vector<vector<string>> SP(4, vector<string>(4, "00"));	
	for (int i = 0; i < 4; i++) {
    
      // GF(2^8)上的矩阵乘法
			SP[i][0] = hexXor(hexXor(hexTimes(A[0], p[i][0]), hexTimes(A[3], p[i][1])), hexXor(hexTimes(A[2], p[i][2]), hexTimes(A[1], p[i][3])));
			SP[i][1] = hexXor(hexXor(hexTimes(A[1], p[i][0]), hexTimes(A[0], p[i][1])), hexXor(hexTimes(A[3], p[i][2]), hexTimes(A[2], p[i][3])));
			SP[i][2] = hexXor(hexXor(hexTimes(A[2], p[i][0]), hexTimes(A[1], p[i][1])), hexXor(hexTimes(A[0], p[i][2]), hexTimes(A[3], p[i][3])));
			SP[i][3] = hexXor(hexXor(hexTimes(A[3], p[i][0]), hexTimes(A[2], p[i][1])), hexXor(hexTimes(A[1], p[i][2]), hexTimes(A[0], p[i][3])));
	}
	SP = transMatrix(SP);  //再转化回去
	return SP;
}

vector<vector<string>> AddRoundKey(vector<vector<string>> P, vector<vector<string>> K, char ed) {
    
      //轮密钥加
	P = transMatrix(P);   //轮密钥加要用列,先翻转一下
	vector<vector<string>> ARK(4, vector<string>(4, "00"));
	if (ed == 'e') {
    
    
		for (int i = 0; i < 4; i++) {
    
    
			for (int j = 0; j < 4; j++) {
    
    
				ARK[i][j] = hexXor(P[i][j], K[flag_e * 4 + i][j]);
			}
		}
	}
	else {
    
    
		for (int i = 0; i < 4; i++) {
    
    
			for (int j = 0; j < 4; j++) {
    
    
				ARK[i][j] = hexXor(P[i][j], K[flag_d * 4 + i][j]);
			}
		}
	}
	ARK = transMatrix(ARK);   //再给他翻转回去
	return ARK;
}

vector<vector<string>> nineRounds(vector<vector<string>> P, vector<vector<string>> K, char ed) {
    
      // 9轮变换
	if (ed == 'e') {
    
    
		for (int i = 0; i < 9; i++) {
    
    
			flag_e++;
			P = subBytes(P, 'e');
			P = ShiftRows(P);
			P = MixColumns(P, MixC);
			P = AddRoundKey(P, K, 'e');
		}
	}
	else {
    
    
		for (int i = 0; i < 9; i++) {
    
    
			flag_d--;
			P = MixColumns(P, MixCni);
			P = invShiftRows(P);
			P = subBytes(P, 'd');
			P = AddRoundKey(P, K, 'd');
		}
	}
	return P;
}

vector<vector<string>> finalRounds(vector<vector<string>> P, vector<vector<string>> K, char ed) {
    
       //最终轮变换
	if (ed == 'e') {
    
    
		flag_e++;
		P = subBytes(P, 'e');
		P = ShiftRows(P);
		P = AddRoundKey(P, K, 'e');
	}
	else {
    
    
		flag_d--;
		P = invShiftRows(P);
		P = subBytes(P, 'd');
		P = AddRoundKey(P, K, 'd');
	}
	return P;
}

string HextoBin(string Hex) {
    
    
    string Bin = "";
    for(int i = 0; i < Hex.length(); i++) {
    
    
        if(Hex[i] == '0') Bin += "0000";
        else if(Hex[i] == '1') Bin += "0001";
        else if(Hex[i] == '2') Bin += "0010";
        else if(Hex[i] == '3') Bin += "0011";
        else if(Hex[i] == '4') Bin += "0100";
        else if(Hex[i] == '5') Bin += "0101";
        else if(Hex[i] == '6') Bin += "0110";
        else if(Hex[i] == '7') Bin += "0111";
        else if(Hex[i] == '8') Bin += "1000";
        else if(Hex[i] == '9') Bin += "1001";
        else if(Hex[i] == 'A') Bin += "1010";
        else if(Hex[i] == 'B') Bin += "1011";
        else if(Hex[i] == 'C') Bin += "1100";
        else if(Hex[i] == 'D') Bin += "1101";
        else if(Hex[i] == 'E') Bin += "1110";
        else Bin += "1111";
    }
    return Bin;
}

string BintoHex(string Bin) {
    
    
    string Hex = "";
    for(int i = 0; i < Bin.length() / 4; i++) {
    
    
        int num = (Bin[4 * i] - '0') * 8 + (Bin[4 * i + 1] - '0') * 4 + (Bin[4 * i + 2] - '0') * 2 + (Bin[4 * i + 3] - '0');
        if(0 <= num && num <= 9) Hex += (num + '0');
        else if(num == 10) Hex += "A";
        else if(num == 11) Hex += "B";
        else if(num == 12) Hex += "C";
        else if(num == 13) Hex += "D";
        else if(num == 14) Hex += "E";
        else Hex += "F";
    }
    return Hex;
}

string LowToUpper(string low) {
    
    
    for(int i = 0; i < low.length(); i++) {
    
    
        if(low[i] >= 'a' && low[i] <= 'z') {
    
    
            low[i] -= 32;
        }
    }
    return low;
}

int HexToDec(char Hex) {
    
    
	if(Hex >= '0' && Hex <= '9')
		return Hex - '0';
	else 
		return Hex - 55;
}

string hexXor(string a, string b) {
    
    
	string A = HextoBin(a);
	string B = HextoBin(b);
	string x(A.length(), '0');
	for (int i = 0; i < A.length(); i++) {
    
    
		x[i] = (A[i] - '0') ^ (B[i] - '0') + '0';
	}
	return BintoHex(x);
}

string hexTimes(string a, string b) {
    
    
	string A = HextoBin(a);
	string B = HextoBin(b);
	string ans(8, '0');
	if (a == "01") {
    
    
		return b;
	}
	else if (a == "02") {
    
    
		for (int i = 0; i < 7; i++) {
    
    
			ans[i] = B[i + 1];
		}
		if (B[0] == '0') {
    
    
			return BintoHex(ans);
		}
		else {
    
    
			return hexXor(BintoHex(ans), "1B");
		}
	}
	else if (a == "03") {
    
    
		return hexXor(hexTimes("02", b), b);
	}
	else if (a == "04") {
    
    
		return hexTimes("02", hexTimes("02", b));
	}
    else if (a == "08") {
    
    
        return hexTimes("02", hexTimes("04", b));
    }
    else if (a == "09") {
    
    
        return hexXor(b, hexTimes("08", b));
    }
    else if (a == "0E") {
    
    
        return hexXor(hexTimes("08", b), hexXor(hexTimes("04", b), hexTimes("02", b)));
    }
    else if (a == "0D") {
    
    
        return hexXor(hexTimes("09", b), hexTimes("04", b));
    }
    else if (a == "0B") {
    
    
        return hexXor(hexTimes("09", b), hexTimes("02", b));
    }
	else {
    
    
		cout << "列混合步骤出错,用到了不支持的矩阵乘法,请检查列混合矩阵!" << endl;
		system("pause");
		return 0;
	}
}

vector<vector<string>> transMatrix(vector<vector<string>> K) {
    
    
	vector<vector<string>> TK(K[0].size(), vector<string>(K.size(), "00"));
	for (int i =0; i < K.size(); i++) {
    
    
		for (int j = 0; j < K[0].size(); j++) {
    
    
			TK[j][i] = K[i][j];
		}
	}
	return TK;
}

int main() {
    
    
	string PATH;
    string p, c, k;   //明文、密文、密钥
	cout << "-------------------AES-128加/解密工具--------------------" << endl << endl;
    cout << "请输入你想加密还是解密,加密为e,解密为d:";
    string ed;
    cin >> ed;
	cout << "\n请输入文件路径:";
	cin >> PATH;
	fstream File(PATH, ios::out|ios::in);   // 以读取和覆盖的方式打开文件
	if(!File.is_open()){
    
    
        cout << "\n打开或创建文件失败,请检查文件是否被占用!\n" << endl;
        system("pause");
        return 0;
    }
	vector<string> textBox;
	while(!File.eof()) {
    
    
		string temp;
		getline(File, temp, '\n');
		textBox.push_back(temp);
	}
	File.seekg(0, ios::beg);  // 回到文件头
	if (textBox.size() == 2) {
    
       // 文件中只有明文和密钥
		p = textBox[0];
		k = textBox[1];
		textBox.push_back("");
	}
	else {
    
                           // 文件中有明文、密钥和密文
		p = textBox[0];
		k = textBox[1];
		c = textBox[2];
	}
	k = LowToUpper(k);
	p = LowToUpper(p);
	c = LowToUpper(c);  // 将读入字符全部变为大写,增加健壮性
	if (ed == "e" || ed == "E") {
    
    
		c = encrypt(p, k);
		textBox[2] = c;
		for (int i = 0; i < textBox.size(); i++) {
    
    
			File << textBox[i];
			if (i != textBox.size() - 1) {
    
    
				File << endl;
			}
		}
		cout << "加密成功,密文已保存至源文件最后一行,请到源文件查看!" << endl;
		File.close();   // 及时关闭文件,防止内存泄露
	}
	else if (ed == "d" || ed == "D") {
    
    
		p = decrypt(c, k);
		textBox[0] = p;
		for (int i = 0; i < textBox.size(); i++) {
    
    
			File << textBox[i];
			if (i != textBox.size() - 1) {
    
    
				File << endl;
			}
		}
		cout << "解密成功,明文已保存至源文件第一行,请到源文件查看!" << endl;
		File.close();
	}
	else {
    
    
		cout << "参数错误!\n" << endl;
		File.close();  // Close the file
		system("pause");
		return 0;
	}
	system("pause");
	return 0;
}

运行结果

加密

加密前(第一行明文,第二行密钥,第三行密文):
在这里插入图片描述
加密过程:
在这里插入图片描述
结果:
在这里插入图片描述
3D 71 F7 44 18 02 79 6D 5B 55 21 66 AB 74 DF EF
A4 32 E2 2D 8B BA 53 62 D5 57 19 35 32 5A D1 32
B5 86 4C 93 73 EF D6 CB 89 E8 12 5F 33 E0 7D E6

解密

解密前:
在这里插入图片描述
解密中:
在这里插入图片描述
解密结果:
在这里插入图片描述
与加密对照之后发现一样,程序运行无误

猜你喜欢

转载自blog.csdn.net/kongtaoxing/article/details/127228448