Re:从零开始的逆向生活05day

前言

没想到这玩意还能继续出,意料之外啊

这次是补坑01day,对称加解密(使用同一个密钥)代表是AES,DES

01day链接:Re:从零开始的逆向生活 01day-CSDN博客

DES

每64bit明文分组,输入到密码器初始置换产生16个子密钥对本身进行16轮变换(第8、16、24、32、40、48、56、64为奇偶校验位),再逆变换得到64bit密文

#include <string.h>
#include <stdio.h>
#include <iostream>
#pragma warning(disable:4996)
using namespace std;
/*
 * @Author:timerring
 * @Date: 2021-11-01 19:17:32
 * @LastEditTime: 2021-11-05 20:34:13
 * @FilePath:c:\Users\timerring\DES.cpp
 */
class DES {
	//构造DES类
public:
	~DES() {}	//定义析构函数 
	void set_key(const unsigned char*);	//密钥扩展
	void en_ctransform(const unsigned char*, unsigned char*); //加密变换
	void de_ctransform(const unsigned char*, unsigned char*); //解密变换
private:
	bool enckey[16][48];//存放加密的子密钥 
	bool deckey[16][48];//存放解密的子密钥

	const static unsigned char IP_Table[64];
	//初置换 

	const static unsigned char IPR_Table[64];
	//逆置换 

	const static unsigned char E_Table[48];
	//E表 

	const static unsigned char P_Table[32];
	//置换选择 

	const static unsigned char PC1_Table[56];
	//置换选择1

	const static unsigned char PC2_Table[48];
	//置换选择2

	const static unsigned char LOOP_Table[16];
	//密钥位移(左移次数) 

	const static unsigned char S_Box[8][4][16];
	// S盒 
};

const unsigned char DES::IP_Table[64] = {
	58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
	62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
	57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
	61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};
// 初置换 

const unsigned char DES::IPR_Table[64] = {
	40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
	38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
	36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
	34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25
};
// 逆初始置换 

const unsigned char DES::E_Table[48] = {
	32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
	 8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
};
// E表 

const unsigned char DES::P_Table[32] = {
	16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,
	2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25
};
// 置换选择 

const unsigned char DES::PC1_Table[56] = {
	57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
	10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
	63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
	14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
};
//置换选择1

const unsigned char DES::PC2_Table[48] = {
	14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
	23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
	41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
	44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};
//置换选择2 

const unsigned char DES::LOOP_Table[16] = {
	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
// 密钥位移(左移次数) 

const unsigned char DES::S_Box[8][4][16] = { 
    //8个S盒 ,每个盒为4行16列
	// 定义S1盒
	14,	 4,	13,	 1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
	 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
	 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
	15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
	// 定义S2盒 
	15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
	 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
	 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
	13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
	// 定义S3盒 
	10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
	13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
	13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
	 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
	// 定义S4盒 
	  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
	 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
	 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
	  3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
	// 定义S5盒 
	   2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
	  14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
	   4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
	  11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
	// 定义S6盒 
	  12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
	  10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
	   9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
	   4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
	// 定义S7盒
		4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
	   13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
		1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
		6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
    // 定义S8盒
		13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
		 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
		 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
		 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
};

void chaifen(char byte, int a[64], int q) {
	int i;
	for (i = 0; i < 8; i++) {
		a[7 - i + q] = byte & 1;
		byte >>= 1;
		//把byte右移一位的值赋值给byte
	}
}

void DES::set_key(unsigned char const* yonghu_key/*用户输入的64位密钥首地址*/) {
	//密钥扩展算法
	int arr[64];
	int ary[56];
	int i, curry = 0;
	for (i = 0; i < 8; i++) {
		chaifen(yonghu_key[i], arr, curry);
		curry = curry + 8;
	}
	for (i = 0; i < 56; i++) {
		ary[i] = arr[PC1_Table[i] - 1];
	}
	for (i = 0; i < 16; i++) {
		if (i == 0 || i == 1 || i == 8 || i == 15) {
			int j, temp0, temp1;
			temp0 = ary[0]; temp1 = ary[28];
			for (j = 0; j < 28; j++) {
				ary[j] = ary[j + 1];
				ary[j + 28] = ary[j + 29];
			}
			ary[27] = temp0; ary[55] = temp1;
		}
		else {
			int j, temp0, temp1;
			temp0 = ary[0]; temp1 = ary[28];
			for (j = 0; j < 28; j++) {
				ary[j] = ary[j + 1];
				ary[j + 28] = ary[j + 29];
			}
			ary[27] = temp0; ary[55] = temp1;
			temp0 = ary[0]; temp1 = ary[28];
			for (j = 0; j < 28; j++) {
				ary[j] = ary[j + 1];
				ary[j + 28] = ary[j + 29];
			}
			ary[27] = temp0; ary[55] = temp1;
		}
		int j;
		for (j = 0; j < 48; j++)
			enckey[i][j] = (bool)ary[PC2_Table[i] - 1];
	}
}


void DES::en_ctransform(const unsigned char* In /*待解密的64位数据首地址*/, unsigned char* Out) {
	//加密变换算法
	int arr[64];
	int ary[64];
	int i, j, curry = 0;
	for (i = 0; i < 8; i++) {
		chaifen(In[i], arr, curry);
		curry = curry + 8;
	}
	for (i = 0; i < 64; i++) {
		ary[i] = arr[IP_Table[i] - 1];
	}

	int larr[32];
	int rarr[32];
	for (i = 0; i < 32; i++) {
		larr[i] = ary[i];
		rarr[i] = ary[i + 32];
	}
	for (i = 0; i < 16; i++) {
		int temp[32];
		for (j = 0; j < 32; j++) {
			temp[j] = larr[j];
			larr[j] = rarr[j];
		}
		int i0, j0, q;
		int e[48];
		for (i0 = 0; i0 < 48; i0++)
			e[i0] = rarr[E_Table[i0] - 1];
		int w;
		for (w = 0; w < 48; w++) {
			e[w] = (e[w] + enckey[i][w]) % 2;
		}

		for (j0 = 0; j0 < 8; j0++) {
			int hang = e[j0 * 6] * 2 + e[j0 * 6 + 5];
			int lie = e[j0 * 6 + 1] * 8 + e[j0 * 6 + 2] * 4 + e[j0 * 6 + 3] * 2 + e[j0 * 6 + 4];
			int num = S_Box[j0][hang][lie];
			for (q = 0; q < 4; q++) {
				rarr[j0 * 4 + 3 - q] = num & 1;
				num >>= 1;
			}
		}
		int temp0[32];
		for (j = 0; j < 32; j++) {
			temp0[j] = rarr[j];
		}
		for (j = 0; j < 32; j++) {
			rarr[j] = temp0[P_Table[j] - 1];
		}

		for (j = 0; j < 32; j++) {
			rarr[j] = ((rarr[j] + temp[j]) % 2);
		}
	}

	int temp[32];
	for (i = 0; i < 32; i++) {
		temp[i] = larr[i];
		larr[i] = rarr[i];
		rarr[i] = temp[i];
	}
	for (i = 0; i < 32; i++) {
		ary[i] = larr[i];
		ary[i + 32] = rarr[i];
	}
	for (i = 0; i < 64; i++) {
		arr[i] = ary[IPR_Table[i] - 1];
	}

	for (i = 0; i < 8; i++) {
		Out[i] = arr[i * 8] * 128 + arr[i * 8 + 1] * 64 + arr[i * 8 + 2] * 32 + arr[i * 8 + 3] * 16 + arr[i * 8 + 4] * 8 + arr[i * 8 + 5] * 4 + arr[i * 8 + 6] * 2 + arr[i * 8 + 7];
	}
}

void DES::de_ctransform(const unsigned char* In /*待加密的64位数据首地址*/, unsigned char* Out) {
	//解密变换算法
	int arr[64];
	int ary[64];
	int i, j, curry = 0;


	for (i = 0; i < 8; i++) {
		chaifen(In[i], arr, curry);
		curry += 8;
	}
	for (i = 0; i < 64; i++) {
		ary[i] = arr[IP_Table[i] - 1];
	}

	int larr[32];
	int rarr[32];
	for (i = 0; i < 32; i++) {
		larr[i] = ary[i];
		rarr[i] = ary[i + 32];
	}


	for (i = 0; i < 16; i++) {
		int temp[32];
		for (j = 0; j < 32; j++) {
			temp[j] = larr[j];
			larr[j] = rarr[j];
		}
		int i0, j0, q;
		int e[48];
		for (i0 = 0; i0 < 48; i0++)
			e[i0] = rarr[E_Table[i0] - 1];
		int w;
		for (w = 0; w < 48; w++) {
			e[w] = (e[w] + enckey[15 - i][w]) % 2;
		}

		for (j0 = 0; j0 < 8; j0++) {
			int hang = e[j0 * 6] * 2 + e[j0 * 6 + 5];
			int lie = e[j0 * 6 + 1] * 8 + e[j0 * 6 + 2] * 4 + e[j0 * 6 + 3] * 2 + e[j0 * 6 + 4];
			int num = S_Box[j0][hang][lie];
			for (q = 0; q < 4; q++) {
				rarr[j0 * 4 + 3 - q] = num & 1;
				num >>= 1;
			}
		}

		int temp0[32];
		for (j = 0; j < 32; j++) {
			temp0[j] = rarr[j];
		}
		for (j = 0; j < 32; j++) {
			rarr[j] = temp0[P_Table[j] - 1];
		}
		for (j = 0; j < 32; j++) {
			rarr[j] = ((rarr[j] + temp[j]) % 2);
		}

	}
	int temp[32];
	for (i = 0; i < 32; i++) {
		temp[i] = larr[i];
		larr[i] = rarr[i];
		rarr[i] = temp[i];
	}

	for (i = 0; i < 32; i++) {
		ary[i] = larr[i];
		ary[i + 32] = rarr[i];
	}
	for (i = 0; i < 64; i++) {
		arr[i] = ary[IPR_Table[i] - 1];
	}
	for (i = 0; i < 8; i++) {
		Out[i] = arr[i * 8] * 128 + arr[i * 8 + 1] * 64 + arr[i * 8 + 2] * 32 + arr[i * 8 + 3] * 16 + arr[i * 8 + 4] * 8 + arr[i * 8 + 5] * 4 + arr[i * 8 + 6] * 2 + arr[i * 8 + 7];
	}
}

int main() {
	unsigned int seq[8];
	unsigned char key[9];	//密钥 
	unsigned char plain[9];	//明文 
	unsigned char cipher[9];//密文 
	char shuruzi[17];	//键盘输入的字符 
	char choice = ' ';
	DES mydes;	//类 
	int i, j;
	int s;

	while (true) {
		cout << "You are welcome to use the DES machine in SDU\n" << endl;
		do {
			cout << "Please enter the corresponding operation number:\n1.Encrypt\t2.Decrypt\t3.Quit" << endl;
			scanf("\n%c", &choice);
		} while (choice != '1' && choice != '2' && choice != '3');

		switch (choice) {
		case '1':
			printf("Please enter the secret key (length = 16):\n");
			scanf("%s", shuruzi);
			sscanf(shuruzi, "%2x%2x%2x%2x%2x%2x%2x%2x", &seq[0], &seq[1], &seq[2], &seq[3], &seq[4], &seq[5], &seq[6], &seq[7]);
			for (i = 0; i < 8; i++)
				key[i] = seq[i];
			//将输入的字符依次存到密钥数组中
			printf("\n");
			printf("Please enter plaintext (length = 16):\n");
			scanf("%s", shuruzi);
			printf("\n");
			sscanf(shuruzi, "%2x%2x%2x%2x%2x%2x%2x%2x", &seq[0], &seq[1], &seq[2], &seq[3], &seq[4], &seq[5], &seq[6], &seq[7]);
			for (j = 0; j < 8; j++)
				plain[j] = seq[j];
			//将输入的字符依次存到明文数组中 

			mydes.set_key(key);
			mydes.en_ctransform(plain, cipher);
			//调用加密算法函数完成加密

			for (s = 0; s < 8; s++)
				seq[s] = cipher[s];
			printf("ciphertext:\n%02x%02x%02x%02x%02x%02x%02x%02x\n", seq[0], seq[1], seq[2], seq[3], seq[4], seq[5], seq[6], seq[7]);
			//将密文数组中的字符存入缓存数组并输出 
			printf("\n");
			break;


		case '2':
			printf("Please enter the secret key (length = 16):\n");
			scanf("%s", shuruzi);
			sscanf(shuruzi, "%2x%2x%2x%2x%2x%2x%2x%2x", &seq[0], &seq[1], &seq[2], &seq[3], &seq[4], &seq[5], &seq[6], &seq[7]);
			for (i = 0; i < 8; i++)
				key[i] = seq[i];
			//将输入的字符依次存到明文数组中 
			printf("\n");
			printf("Please enter the ciphertext (length = 16):\n");
			scanf("%s", shuruzi);
			printf("\n");
			sscanf(shuruzi, "%2x%2x%2x%2x%2x%2x%2x%2x", &seq[0], &seq[1], &seq[2], &seq[3], &seq[4], &seq[5], &seq[6], &seq[7]);
			for (j = 0; j < 8; j++)
				cipher[j] = seq[j];
			//将输入的字符依次存到密文数组中 

			mydes.set_key(key);
			mydes.de_ctransform(cipher, plain);
			//调用解密算法函数完成解密
			for (s = 0; s < 8; s++)
				seq[s] = plain[s];
			printf("plaintext:\n%02x%02x%02x%02x%02x%02x%02x%02x\n", seq[0], seq[1], seq[2], seq[3], seq[4], seq[5], seq[6], seq[7]);
			printf("\n");
			break;
		case '3':
			return 0;
			break;
		}
	}
}

参考资料:DES加解密算法原理详解与实现_des加密解密原理及流程-CSDN博客

AES

数据分组长度为 128 bits,使用的密钥长度为 128、192 或 256 bits,每轮的密钥由种子密钥经过密钥扩展算法得到,算法中16字节的明文、密文和轮子密钥都以一个4x4的矩阵表示

#include <stdio.h>
#pragma warning(disable:4996)
/*
 * @Author:timerring
 * @Date: 2021-11-08 21:59:11
 * @LastEditTime: 2021-11-12 23:44:19
 * @FilePath:c:\Users\timerring\AES.cpp
 */
 //定义轮常量表
static const unsigned char Rcon[10] = {
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36 };

//定义有限域*2乘法
static unsigned char x2time(unsigned char x)
{
	if (x & 0x80)
	{
		return (((x << 1) ^ 0x1B) & 0xFF);
	}
	return x << 1;
}
//定义有限域*3乘法
static unsigned char x3time(unsigned char x)
{
	return (x2time(x) ^ x);
}
//定义有限域*4乘法
static unsigned char x4time(unsigned char x)
{
	return (x2time(x2time(x)));
}
//定义有限域*8乘法
static unsigned char x8time(unsigned char x)
{
	return (x2time(x2time(x2time(x))));
}
//定义有限域*9乘法
static unsigned char x9time(unsigned char x)
{
	return (x8time(x) ^ x);
}
//定义有限域*B乘法
static unsigned char xBtime(unsigned char x)
{
	return (x8time(x) ^ x2time(x) ^ x);
}
//定义有限域*D乘法
static unsigned char xDtime(unsigned char x)
{
	return (x8time(x) ^ x4time(x) ^ x);
}
//定义有限域*E乘法
static unsigned char xEtime(unsigned char x)
{
	return (x8time(x) ^ x4time(x) ^ x2time(x));
}
//s盒矩阵 Substitution Table
static const unsigned char sbox[256] = {
	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,
	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,
	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,
	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,
	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,
	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,
	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,
	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,
	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,
	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,
	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,
	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,
	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,
	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,
	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,
	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,
	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
};
//逆向S盒矩阵
static const unsigned char contrary_sbox[256] = {
	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d,
};
//定义列混合操作
static void MixColumns(unsigned char* col)
{
	unsigned char tmp[4], xt[4];
	int i;
	for (i = 0; i < 4; i++, col += 4)
	{  //col代表一列的基地址,col+4:下一列的基地址
		//xt[n]代表*2   xt[n]^col[n]代表*3   col[n]代表*1
		tmp[0] = x2time(col[0]) ^ x3time(col[1]) ^ col[2] ^ col[3];	//2 3 1 1
		tmp[1] = col[0] ^ x2time(col[1]) ^ x3time(col[2]) ^ col[3];	//1 2 3 1
		tmp[2] = col[0] ^ col[1] ^ x2time(col[2]) ^ x3time(col[3]);	//1 1 2 3
		tmp[3] = x3time(col[0]) ^ col[1] ^ col[2] ^ x2time(col[3]);	//3 1 1 2
		//修改后的值 直接在原矩阵上修改
		col[0] = tmp[0];
		col[1] = tmp[1];
		col[2] = tmp[2];
		col[3] = tmp[3];
	}
}
//定义逆向列混淆
static void Contrary_MixColumns(unsigned char* col)
{
	unsigned char tmp[4];
	unsigned char xt2[4];//colx2
	unsigned char xt4[4];//colx4
	unsigned char xt8[4];//colx8
	int x;
	for (x = 0; x < 4; x++, col += 4)
	{
		tmp[0] = xEtime(col[0]) ^ xBtime(col[1]) ^ xDtime(col[2]) ^ x9time(col[3]);
		tmp[1] = x9time(col[0]) ^ xEtime(col[1]) ^ xBtime(col[2]) ^ xDtime(col[3]);
		tmp[2] = xDtime(col[0]) ^ x9time(col[1]) ^ xEtime(col[2]) ^ xBtime(col[3]);
		tmp[3] = xBtime(col[0]) ^ xDtime(col[1]) ^ x9time(col[2]) ^ xEtime(col[3]);
		col[0] = tmp[0];
		col[1] = tmp[1];
		col[2] = tmp[2];
		col[3] = tmp[3];
	}
}
//定义行移位操作:行左循环移位
static void ShiftRows(unsigned char* col)
{//正向行移位
	unsigned char t;
	//左移1位
	t = col[1]; col[1] = col[5]; col[5] = col[9]; col[9] = col[13]; col[13] = t;
	//左移2位,交换2次数字来实现
	t = col[2]; col[2] = col[10]; col[10] = t;
	t = col[6]; col[6] = col[14]; col[14] = t;
	//左移3位,相当于右移1次
	t = col[15]; col[15] = col[11]; col[11] = col[7]; col[7] = col[3]; col[3] = t;
	//第4行不移位
}
//逆向行移位
static void Contrary_ShiftRows(unsigned char* col)
{
	unsigned char t;
	t = col[13]; col[13] = col[9]; col[9] = col[5]; col[5] = col[1]; col[1] = t;
	t = col[2]; col[2] = col[10]; col[10] = t;
	t = col[6]; col[6] = col[14]; col[14] = t;
	t = col[3]; col[3] = col[7]; col[7] = col[11]; col[11] = col[15]; col[15] = t;
	//同理,第4行不移位
}
//定义s盒字节代换替换操作
static void SubBytes(unsigned char* col)
{//字节代换
	int x;
	for (x = 0; x < 16; x++)
	{
		col[x] = sbox[col[x]];
	}
}
//逆向字节代换
static void Contrary_SubBytes(unsigned char* col)
{
	int x;
	for (x = 0; x < 16; x++)
	{
		col[x] = contrary_sbox[col[x]];
	}
}
//密钥编排,16字节--->44列32bit密钥生成--> 11组16字节:分别用于11轮 轮密钥加运算
void ScheduleKey(unsigned char* inkey, unsigned char* outkey, int Nk, int Nr)
{
	//inkey:初始16字节密钥key
	//outkey:11组*16字节扩展密钥expansionkey
	//Nk:4列
	//Nr:10轮round
	unsigned char temp[4], t;
	int x, i;
	/*copy the key*/
	//第0组:[0-3]直接拷贝
	for (i = 0; i < (4 * Nk); i++)
	{
		outkey[i] = inkey[i];
	}
	//第1-10组:[4-43]
	i = Nk;
	while (i < (4 * (Nr + 1))) //i=4~43 WORD 32bit的首字节地址,每一个4字节
	{//1次循环生成1个字节扩展密钥,4次循环生成一个WORD
		//temp:4字节数组:代表一个WORD密钥
		//i不是4的倍数的时候
		//每个temp = 每个outkey32bit = 4字节
		for (x = 0; x < 4; x++)
			temp[x] = outkey[(4 * (i - 1)) + x];	//i:32bit的首字节地址
		//i是4的倍数的时候
		if (i % Nk == 0)
		{
			/*字循环:循环左移1字节 RotWord()*/
			t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t;
			/*字节代换:SubWord()*/
			for (x = 0; x < 4; x++)
			{
				temp[x] = sbox[temp[x]];
			}
			/*轮常量异或:Rcon[j]*/
			temp[0] ^= Rcon[(i / Nk) - 1];
		}
		for (x = 0; x < 4; x++)
		{
			outkey[(4 * i) + x] = outkey[(4 * (i - Nk)) + x] ^ temp[x];
		}
		++i;
	}
}
//定义轮密钥加操作
static void AddRoundKey(unsigned char* col, unsigned char* expansionkey, int round)//密匙加
{
	//扩展密钥:44*32bit =11*4* 4*8 =  16字节*11轮,每轮用16字节密钥
	//第0轮,只进行一次轮密钥加
	//第1-10轮,轮密钥加
	int x;
	for (x = 0; x < 16; x++)
	{	//每1轮操作:4*32bit密钥 = 16个字节密钥
		col[x] ^= expansionkey[(round << 4) + x];
	}
}
//AES加密函数
void AesEncrypt(unsigned char* blk, unsigned char* expansionkey, int Nr)
{//加密一个区块
	//输入blk原文,直接在上面修改,输出blk密文
	//输入skey:
	//输入Nr = 10轮
	int round;
	//第1轮之前:轮密钥加
	AddRoundKey(blk, expansionkey, 0);
	//第1-9轮:4类操作:字节代换、行移位、列混合、轮密钥加
	for (round = 1; round <= (Nr - 1); round++)
	{
		SubBytes(blk);		//输入16字节数组,直接在原数组上修改
		ShiftRows(blk);		//输入16字节数组,直接在原数组上修改
		MixColumns(blk);	//输入16字节数组,直接在原数组上修改
		AddRoundKey(blk, expansionkey, round);
	}
	//第10轮:不进行列混合
	SubBytes(blk);
	ShiftRows(blk);
	AddRoundKey(blk, expansionkey, Nr);
}
//AES 解密函数
void Contrary_AesEncrypt(unsigned char* blk, unsigned char* expansionkey, int Nr)
{
	int x;
	AddRoundKey(blk, expansionkey, Nr);
	Contrary_ShiftRows(blk);
	Contrary_SubBytes(blk);
	for (x = (Nr - 1); x >= 1; x--)
	{
		AddRoundKey(blk, expansionkey, x);
		Contrary_MixColumns(blk);
		Contrary_ShiftRows(blk);
		Contrary_SubBytes(blk);
	}
	AddRoundKey(blk, expansionkey, 0);
}
int main(void) {
	unsigned char pt[17], key[17];
	//定义原文pt
	//定义密钥key
	unsigned char expansionkey[15 * 16];
	int i;
	int j;
	printf("You are welcome to use the AES machine in SDU\n");
	printf("Please enter plaintext (length = 16):\n");
	scanf("%s", pt);
	printf("please input key:\n");
	scanf("%s", key);

	//加密过程
	ScheduleKey(key, expansionkey, 4, 10);//密钥扩展生成
	AesEncrypt(pt, expansionkey, 10);//调用AES 加密
	printf("ciphertext: ");	
	//输出密文
	for (i = 0; i < 16; i++)
	{
		printf("%02x ", pt[i]);
	}
	printf("\n");
	printf("\n");

	//解密过程
	Contrary_AesEncrypt(pt, expansionkey, 10);//调用AES 解密
	printf("The decrypted plaintext is: ");
	//输出明文
	for (i = 0; i < 16; i++)
	{
		printf("%c ", pt[i]);
	}
	printf("\n");
	printf("\n");
	while (1);
	return 0;
}

参考资料:AES加解密原理详解与算法实现-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值