基于VC++的 AES实现
- 格式:docx
- 大小:594.21 KB
- 文档页数:6
用VC++实现AES的Rijndael算法
郭超;方妮
【期刊名称】《工程物理研究院科技年报》
【年(卷),期】2004(000)001
【摘要】美国国家标准技术研究所(NIST)的数据加密标准DES连续使用了20
年之后,庞大的并行网络电脑攻击和特定的“DES—Cracking”硬件攻克使其安
全性受到了威胁,因此NIST决定用AES(高级加密标准)替代DES,并选择Rijndael作为AES的算法。
来自比利时的两位密码专家开发的Rijndael算法汇聚了安全,性能,效率,易用和灵活等优点,使它成为AES最合适的:选择,Rijndael在不同硬件和软件运行环境下表现出始终如一的良好性能,而无论这些
环境是否有反馈模式,它的密钥设置时间相当出色,密钥的灵敏性也不错。
Rijndael非常低的内存需求也使它很适合用于受限环境中。
Rijndael的操作简单,并可抵御强大和实时的攻击。
【总页数】2页(P374-375)
【作者】郭超;方妮
【作者单位】无
【正文语种】中文
【中图分类】TP311.52
【相关文献】
1.AES/Rijndael算法协处理器设计与实现 [J], 徐志军;周顺;谢波
2.基于VC++的AES算法的实现 [J], 陶小艳
3.AES-Rijndael算法综述 [J], 杨景辉;王丽娜;于戈
4.AES——Rijndael算法在IPSec VPN中的应用 [J], 王敏;王文德
5.AES-Rijndael算法在IPSec VPN中的应用 [J], 王文德;王敏;王贵杰
因版权原因,仅展示原文概要,查看原文内容请购买。
AES算法C语言讲解与实现AES(Advanced Encryption Standard)是一种对称加密算法,被广泛应用于各种应用中,如保护通信、数据安全等。
AES算法采用分组密码的方式,将明文数据分成若干个大小相等的分组,然后对每个分组进行加密操作。
1. 密钥扩展(Key Expansion):AES算法中使用的密钥长度分为128位、192位和256位三种,密钥长度不同,密钥扩展的轮数也不同。
根据密钥长度,需要扩展成多少个轮密钥。
扩展过程中需要进行字节代换、循环左移、模2乘法等操作。
2. 子密钥生成(Subkey Generation):根据密钥扩展的结果,生成每一轮需要使用的子密钥。
3. 字节替换(SubBytes):将每个字节替换为S盒中对应的值。
S盒是一个固定的预先计算好的查找表。
4. 行移位(ShiftRows):对矩阵的行进行循环左移,左移的位数根据行数而定。
5. 列混合(MixColumns):将每列的四个字节进行混合。
混合操作包括乘法和异或运算。
6. 轮密钥加(AddRoundKey):将每一轮得到的结果与轮密钥进行异或运算。
以上就是AES算法的六个步骤的实现过程,下面我们来具体讲解一下。
首先,我们需要定义一些辅助函数,如字节代换函数、循环左移函数等。
```cuint8_t substitution(uint8_t byte) return sBox[byte];void shiftRows(uint8_t *state)uint8_t temp;//第二行循环左移1位temp = state[1];state[1] = state[5];state[5] = state[9];state[9] = state[13];state[13] = temp;//第三行循环左移2位temp = state[2];state[2] = state[10];state[10] = temp;temp = state[6];state[6] = state[14];state[14] = temp;//第四行循环左移3位temp = state[15];state[15] = state[11];state[11] = state[7];state[7] = state[3];state[3] = temp;void mixColumns(uint8_t *state)int i;uint8_t temp[4];for(i = 0; i < 4; i++)temp[0] = xTime(state[i * 4]) ^ xTime(state[i * 4 + 1]) ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[1] = state[i * 4] ^ xTime(state[i * 4 + 1]) ^xTime(state[i * 4 + 2]) ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[2] = state[i * 4] ^ state[i * 4 + 1] ^ xTime(state[i * 4 + 2]) ^xTime(state[i * 4 + 3]) ^ state[i * 4 + 3];temp[3] = xTime(state[i * 4]) ^ state[i * 4] ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ xTime(state[i * 4 + 3]);state[i * 4] = temp[0];state[i * 4 + 1] = temp[1];state[i * 4 + 2] = temp[2];state[i * 4 + 3] = temp[3];}```接下来,我们实现密钥扩展和子密钥生成的过程。
///////////头文件-------begin-----------------------------------------#ifndef AES_H_#define AES_H_#include <string>using std::string;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////class AES{public:AES();//AES(const char *cchKey);~AES();public://加密文件数据int EncryptFile(const char *cszpSourceFileName,const char *cszpPwdFileName,const char *cszpKey);//解密文件数据int DecryptFile(const char *cszpPwdFileName,const char *cszpResultFileName,const char *cszpKey);//加密字符串string EncryptText(const char *pszInText,const char *cszpKey);//解密字符串string DecryptText(const char *pszInText,const char *cszpKey);//备份数据int BackUp(const char *cszpData, const char *cszpKey, const char *cszpFileName);//恢复备份的数据string Recover(const char *cszpKey, const char *cszpFileName);private:int ByteToBit(char ch,char bit[8]);int BitToByte(char bit[8],char *ch);int Char8ToBit64(char ch[8],char bit[64]);int Bit64ToChar8(char bit[64],char ch[8]);int DES_MakeSubKeys(char key[64],char subKeys[16][48]);int DES_PC1_Transform(char key[64], char tempbts[56]);int DES_PC2_Transform(char key[56], char tempbts[48]);int DES_ROL(char data[56], int time);int DES_IP_Transform(char data[64]);int DES_IP_1_Transform(char data[64]);int DES_E_Transform(char data[48]);int DES_P_Transform(char data[32]);int DES_SBOX(char data[48]);int DES_XOR(char R[48], char L[48],int count);int DES_Swap(char left[32],char right[32]);int DES_EncryptBlock(char plainBlock[8], char subKeys[16][48], char cipherBlock[8]);int DES_DecryptBlock(char cipherBlock[8], char subKeys[16][48], char plainBlock[8]); };#endif /* AES_H_ *////////////头文件-------end-----------------------------------------//以下是实现文件#include "stdafx.h"#include <string>#include <stdio.h>#include <memory.h>#include <time.h>#include <stdlib.h>#include "AES.h"using namespace std;#define PLAIN_FILE_OPEN_ERROR -1#define KEY_FILE_OPEN_ERROR -2#define CIPHER_FILE_OPEN_ERROR -3#define OK 1#define PARAM_ERROR -1///////////////////////////////////////////////////////////////////////////*初始置换表IP*/int IP_Table[64] = { 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,56,48,40,32,24,16,8,0,58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,62,54,46,38,30,22,14,6};/*逆初始置换表IP^-1*/int IP_1_Table[64] = {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,32,0,40,8,48,16,56,24};/*扩充置换表E*/int E_Table[48] = {31, 0, 1, 2, 3, 4,3, 4, 5, 6, 7, 8,7, 8,9,10,11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,21,22,23,24,23,24,25,26,27,28,27,28,29,30,31, 0};/*置换函数P*/int P_Table[32] = {15,6,19,20,28,11,27,16,0,14,22,25,4,17,30,9,1,7,23,13,31,26,2,8,18,12,29,5,21,10,3,24};/*S盒*/int S[8][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}}};/*置换选择1*/int PC_1[56] = {56,48,40,32,24,16,8,0,57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,60,52,44,36,28,20,12,4,27,19,11,3};/*置换选择2*/int PC_2[48] = {13,16,10,23,0,4,2,27,14,5,20,9,22,18,11,3,25,7,15,6,26,19,12,1,40,51,30,36,46,54,29,39,50,44,32,46,43,48,38,55,33,52,45,41,49,35,28,31};/*对左移次数的规定*/int MOVE_TIMES[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};//////////////////////////////////////////////////////////////////////////AES::AES(){}// AES::AES(const char *cchKey)// {//// }AES::~AES(){}/*字节转换成二进制*/int AES::ByteToBit(char ch, char bit[8]){if (bit == NULL){return PARAM_ERROR;}int cnt = 0;for(cnt = 0;cnt < 8; cnt++){*(bit+cnt) = (ch>>cnt)&1;}return 0;}/*二进制转换成字节*/int AES::BitToByte(char bit[8],char *ch){ if ((ch == NULL) || (bit == NULL)){return PARAM_ERROR;}int cnt = 0;for(cnt = 0;cnt < 8; cnt++){*ch |= *(bit + cnt)<<cnt;}return 0;}/*将长度为8的字符串转为二进制位串*/ int AES::Char8ToBit64(char ch[8],char bit[64]){ if ((ch == NULL) || (bit == NULL)){return PARAM_ERROR;}int cnt = 0;for(cnt = 0; cnt < 8; cnt++){ByteToBit(*(ch+cnt),bit+(cnt<<3));}return 0;}/*将二进制位串转为长度为8的字符串*/ int AES::Bit64ToChar8(char bit[64],char ch[8]){ if ((ch == NULL) || (bit == NULL)){return PARAM_ERROR;}int cnt = 0;memset(ch,0,8);for(cnt = 0; cnt < 8; cnt++){BitToByte(bit+(cnt<<3),ch+cnt);}return 0;}/*生成子密钥*/int AES::DES_MakeSubKeys(char key[64],char subKeys[16][48]){if ((key == NULL) || (subKeys == NULL)){return PARAM_ERROR;}char temp[56] = {0};int cnt = 0;if(DES_PC1_Transform(key,temp) < 0)/*PC1置换*/{return -2;}for(cnt = 0; cnt < 16; cnt++){/*16轮跌代,产生16个子密钥*/DES_ROL(temp,MOVE_TIMES[cnt]);/*循环左移*/DES_PC2_Transform(temp,subKeys[cnt]);/*PC2置换,产生子密钥*/ }return 0;}/*密钥置换1*/int AES::DES_PC1_Transform(char key[64], char tempbts[56]){if ((key == NULL) || (tempbts == NULL)){return PARAM_ERROR;}int cnt = 0;for(cnt = 0; cnt < 56; cnt++){tempbts[cnt] = key[PC_1[cnt]];}return 0;}/*密钥置换2*/int AES::DES_PC2_Transform(char key[56], char tempbts[48]){if ((key == NULL) || (tempbts == NULL)){return PARAM_ERROR;}int cnt = 0;for(cnt = 0; cnt < 48; cnt++){tempbts[cnt] = key[PC_2[cnt]];}return 0;}/*循环左移*/int AES::DES_ROL(char data[56], int time){ if ((data == NULL) || (time < 0)){return PARAM_ERROR;}char temp[56] = {0};/*保存将要循环移动到右边的位*/memcpy(temp,data,time);memcpy(temp+time,data+28,time);/*前28位移动*/memcpy(data,data+time,28-time);memcpy(data+28-time,temp,time);/*后28位移动*/memcpy(data+28,data+28+time,28-time);memcpy(data+56-time,temp+time,time);return 0;}/*IP置换*/int AES::DES_IP_Transform(char data[64]){ if (data == NULL){return PARAM_ERROR;}int cnt = 0;char temp[64] = {0};for(cnt = 0; cnt < 64; cnt++){temp[cnt] = data[IP_Table[cnt]];}memcpy(data,temp,64);return 0;}/*IP逆置换*/int AES::DES_IP_1_Transform(char data[64]){ if (data == NULL){return PARAM_ERROR;}int cnt = 0;char temp[64] = {0};for(cnt = 0; cnt < 64; cnt++){temp[cnt] = data[IP_1_Table[cnt]];}memcpy(data,temp,64);return 0;}/*扩展置换*/int AES::DES_E_Transform(char data[48]){ if (data == NULL){return PARAM_ERROR;}int cnt = 0;char temp[48] = {0};for(cnt = 0; cnt < 48; cnt++){temp[cnt] = data[E_Table[cnt]];}memcpy(data,temp,48);return 0;}/*P置换*/int AES::DES_P_Transform(char data[32]){ if (data == NULL){return PARAM_ERROR;}int cnt = 0;char temp[32] = {0};for(cnt = 0; cnt < 32; cnt++){temp[cnt] = data[P_Table[cnt]];}memcpy(data,temp,32);return 0;}/*异或*/int AES::DES_XOR(char R[48], char L[48] ,int count){ if ((R == NULL) || (L == NULL)){return PARAM_ERROR;}int cnt = 0;for(cnt = 0; cnt < count; cnt++){R[cnt] ^= L[cnt];}return 0;}/*S盒置换*/int AES::DES_SBOX(char data[48]){if(data == NULL){return PARAM_ERROR;}int cnt = 0;int line = 0;int row = 0;int output = 0;int cur1 = 0,cur2 = 0;for(cnt = 0; cnt < 8; cnt++){cur1 = cnt*6;cur2 = cnt<<2;/*计算在S盒中的行与列*/line = (data[cur1]<<1) + data[cur1+5];row = (data[cur1+1]<<3) + (data[cur1+2]<<2)+ (data[cur1+3]<<1) + data[cur1+4];output = S[cnt][line][row];/*化为2进制*/data[cur2] = (output&0X08)>>3;data[cur2+1] = (output&0X04)>>2;data[cur2+2] = (output&0X02)>>1;data[cur2+3] = output&0x01;}return 0;}/*交换*/int AES::DES_Swap(char left[32], char right[32]){if((left == NULL) || (right == NULL)){return PARAM_ERROR;}char temp[32] = {0};memcpy(temp,left,32);memcpy(left,right,32);memcpy(right,temp,32);return 0;}/*加密单个分组*/int AES::DES_EncryptBlock(char plainBlock[8], char subKeys[16][48], char cipherBlock[8]){if((plainBlock == NULL) || (subKeys == NULL) || (cipherBlock == NULL)){return PARAM_ERROR;}char plainBits[64] = {0};char copyRight[48] = {0};int cnt = 0;Char8ToBit64(plainBlock,plainBits);/*初始置换(IP置换)*/DES_IP_Transform(plainBits);/*16轮迭代*/for(cnt = 0; cnt < 16; cnt++){memcpy(copyRight,plainBits+32,32);/*将右半部分进行扩展置换,从32位扩展到48位*/DES_E_Transform(copyRight);/*将右半部分与子密钥进行异或操作*/DES_XOR(copyRight,subKeys[cnt],48);/*异或结果进入S盒,输出32位结果*/DES_SBOX(copyRight);/*P置换*/DES_P_Transform(copyRight);/*将明文左半部分与右半部分进行异或*/DES_XOR(plainBits,copyRight,32);if(cnt != 15){/*最终完成左右部的交换*/DES_Swap(plainBits,plainBits+32);}}/*逆初始置换(IP^1置换)*/DES_IP_1_Transform(plainBits);Bit64ToChar8(plainBits,cipherBlock);return 0;}/*解密单个分组*/int AES::DES_DecryptBlock(char cipherBlock[8], char subKeys[16][48],char plainBlock[8]){ if((plainBlock == NULL) || (subKeys == NULL) || (cipherBlock == NULL)){return PARAM_ERROR;}char cipherBits[64] = {0};char copyRight[48] = {0};int cnt = 0;Char8ToBit64(cipherBlock,cipherBits);/*初始置换(IP置换)*/DES_IP_Transform(cipherBits);/*16轮迭代*/for(cnt = 15; cnt >= 0; cnt--){memcpy(copyRight,cipherBits+32,32);/*将右半部分进行扩展置换,从32位扩展到48位*/DES_E_Transform(copyRight);/*将右半部分与子密钥进行异或操作*/DES_XOR(copyRight,subKeys[cnt],48);/*异或结果进入S盒,输出32位结果*/DES_SBOX(copyRight);/*P置换*/DES_P_Transform(copyRight);/*将明文左半部分与右半部分进行异或*/DES_XOR(cipherBits,copyRight,32);if(cnt != 0){/*最终完成左右部的交换*/DES_Swap(cipherBits,cipherBits+32);}}/*逆初始置换(IP^1置换)*/DES_IP_1_Transform(cipherBits);Bit64ToChar8(cipherBits,plainBlock);return 0;}/*功能:加密文件参数:[cszpSourceFileName]:原数据文件名[cszpPwdFileName]:密码文件名[cszpKey]:密码*/int AES::EncryptFile(const char *cszpSourceFileName,const char *cszpPwdFileName,const char *cszpKey){if ((cszpSourceFileName == NULL) ||(cszpPwdFileName == NULL) ||(cszpKey == NULL)){return PARAM_ERROR;}FILE *plain = NULL,*cipher = NULL;int count = 0;char plainBlock[8] = {0};char cipherBlock[8] = {0};char keyBlock[8] = {0};char bKey[64] = {0};char subKeys[16][48] = {0};if((plain = fopen(cszpSourceFileName,("rb"))) == NULL){ return PLAIN_FILE_OPEN_ERROR;}if((cipher = fopen(cszpPwdFileName,"wb")) == NULL){ return CIPHER_FILE_OPEN_ERROR;}/*设置密钥*/memcpy(keyBlock,cszpKey,8);/*将密钥转换为二进制流*/Char8ToBit64(keyBlock,bKey);/*生成子密钥*/DES_MakeSubKeys(bKey,subKeys);while(!feof(plain)){/*每次读8个字节,并返回成功读取的字节数*/if((count = fread(plainBlock,sizeof(char),8,plain)) == 8){DES_EncryptBlock(plainBlock,subKeys,cipherBlock);fwrite(cipherBlock,sizeof(char),8,cipher);}}if(count){/*填充*/memset(plainBlock + count,'\0',7 - count);/*最后一个字符保存包括最后一个字符在内的所填充的字符数量*/plainBlock[7] = 8 - count;DES_EncryptBlock(plainBlock,subKeys,cipherBlock);fwrite(cipherBlock,sizeof(char),8,cipher);}fclose(plain);plain = NULL;fclose(cipher);cipher = NULL;return OK;}/*功能:解密文件参数:[cszpPwdFileName]:密码文件名[cszpResultFileName]:解密后数据文件名[cszpKey]:密码*/int AES::DecryptFile(const char *cszpPwdFileName,const char *cszpResultFileName,const char *cszpKey){if ((cszpResultFileName == NULL) ||(cszpPwdFileName == NULL) ||(cszpKey == NULL)){return PARAM_ERROR;}FILE *plain = NULL, *cipher = NULL;int count,times = 0;long fileLen = 0;char plainBlock[8] = {0};char cipherBlock[8] = {0};char keyBlock[8] = {0};char bKey[64] = {0};char subKeys[16][48] = {0};if((cipher = fopen(cszpPwdFileName,"rb")) == NULL){ return CIPHER_FILE_OPEN_ERROR;}if((plain = fopen(cszpResultFileName,"wb")) == NULL){ return PLAIN_FILE_OPEN_ERROR;}/*设置密钥*/memcpy(keyBlock,cszpKey,8);/*将密钥转换为二进制流*/Char8ToBit64(keyBlock,bKey);/*生成子密钥*/DES_MakeSubKeys(bKey,subKeys);/*取文件长度*/fseek(cipher,0,SEEK_END);/*将文件指针置尾*/ fileLen = ftell(cipher); /*取文件指针当前位置*/ rewind(cipher); /*将文件指针重指向文件头*/while(1){/*密文的字节数一定是8的整数倍*/fread(cipherBlock,sizeof(char),8,cipher);DES_DecryptBlock(cipherBlock,subKeys,plainBlock);times += 8;if(times < fileLen){fwrite(plainBlock,sizeof(char),8,plain);}else{break;}}/*判断末尾是否被填充*/if(plainBlock[7] < 8){for(count = 8 - plainBlock[7]; count < 7; count++){if(plainBlock[count] != '\0'){break;}}}if(count == 7){/*有填充*/fwrite(plainBlock,sizeof(char),8 - plainBlock[7],plain);}else{/*无填充*/fwrite(plainBlock,sizeof(char),8,plain);}fclose(plain);plain = NULL;fclose(cipher);cipher = NULL;return OK;}/*功能:加密字符串参数:[pszInText]:要加密的字符串[cszpKey]:密码*/string AES::EncryptText(const char *pszInText,const char *cszpKey){if ((pszInText == NULL) ||(cszpKey == NULL)){return "";}int count = 0;char plainBlock[9] = {0};char cipherBlock[9] = {0};char keyBlock[9] = {0};char bKey[64] = {0};char subKeys[16][48] = {0};int nSize = strlen(pszInText);char *pchData = (char *)malloc(nSize + 1);if (pchData == NULL){return "";}memset(pchData, 0, nSize + 1);memcpy(pchData, pszInText, nSize);/*设置密钥*/memcpy(keyBlock,cszpKey,8);/*将密钥转换为二进制流*/Char8ToBit64(keyBlock,bKey);/*生成子密钥*/DES_MakeSubKeys(bKey,subKeys);string strData;char *pch = pchData;do{memset(plainBlock, 0, 9);memcpy(plainBlock, pch, 8);int nLen = strlen(plainBlock);if (nLen < 8){count = nLen;break;}else{DES_EncryptBlock(plainBlock,subKeys,cipherBlock);strData += cipherBlock;pch += 8;}} while (true);if(count){/*填充*/memset(plainBlock + count,'\0',7 - count);/*最后一个字符保存包括最后一个字符在内的所填充的字符数量*/ plainBlock[7] = 8 - count;DES_EncryptBlock(plainBlock,subKeys,cipherBlock);strData += cipherBlock;}return strData;}/*功能:解密字符串参数:[pszInText]:要解密的字符串,即加密后的字符串[cszpKey]:密码*/string AES::DecryptText(const char *pszInText,const char *cszpKey) {if ((pszInText == NULL) ||(cszpKey == NULL)){return "";}int count = 0;int times = 0;char plainBlock[9] = {0};char cipherBlock[9] = {0};char keyBlock[9] = {0};char bKey[64] = {0};char subKeys[16][48] = {0};int nSize = strlen(pszInText);char *pchData = (char *)malloc(nSize + 1);if (pchData == NULL){return "";}memset(pchData, 0, nSize + 1);memcpy(pchData, pszInText, nSize);/*设置密钥*/memcpy(keyBlock,cszpKey,8);/*将密钥转换为二进制流*/Char8ToBit64(keyBlock,bKey);/*生成子密钥*/DES_MakeSubKeys(bKey,subKeys);string strData;char *pch = pchData;while(true){/*密文的字节数一定是8的整数倍*/memset(cipherBlock, 0, 9);memset(plainBlock, 0, 9);memcpy(cipherBlock,pch,8);DES_DecryptBlock(cipherBlock,subKeys,plainBlock);times += 8;pch += 8;if(times < nSize){strData += plainBlock;}else{break;}}/*判断末尾是否被填充*/if(plainBlock[7] < 8){for(count = 8 - plainBlock[7]; count < 7; count++){if(plainBlock[count] != '\0'){break;}}}if(count == 7){/*有填充*/memset(cipherBlock, 0, 9);memcpy(cipherBlock,plainBlock,8 - plainBlock[7]);strData += cipherBlock;}else{/*无填充*/memset(cipherBlock, 0, 9);memcpy(cipherBlock,plainBlock,8);strData += cipherBlock;}return strData;}/*功能:备份数据至指定的文件中参数:【cszpData】:要备份的数据【cszpKey】:用于对数据加密的密码【cszpFileName】:保存数据的文件名返回值:成功:大于等于零(>=0)失败:小于零(<0)*/int AES::BackUp(const char *cszpData, const char *cszpKey, const char *cszpFileName) {if ((cszpData == NULL) ||(cszpKey == NULL) ||(cszpFileName == NULL)){return PARAM_ERROR;}string strData = EncryptText(cszpData, cszpKey);if (strData.empty()){return -2;}FILE *pfile = NULL;if((pfile = fopen(cszpFileName,"wb")) == NULL){return CIPHER_FILE_OPEN_ERROR;}fwrite(strData.c_str(), strlen(strData.c_str()), 1, pfile);fclose(pfile);pfile = NULL;return 0;}//恢复备份的数据/*功能:从指定的文件中恢复备份的数据参数:【cszpKey】:用于对数据解密的密码【cszpFileName】:保存数据的文件名返回值:成功:解密后的数据失败:空值*/string AES::Recover(const char *cszpKey, const char *cszpFileName) {if ((cszpKey == NULL) || (cszpFileName == NULL)){return "";}string strData;FILE *pfile = NULL;if ((pfile = fopen(cszpFileName, "rb")) == NULL){return "";}/*取文件长度*/fseek(pfile,0,SEEK_END);/*将文件指针置尾*/long fileLen = ftell(pfile); /*取文件指针当前位置*/rewind(pfile); /*将文件指针重指向文件头*/char *szpFileData = (char *)malloc(fileLen + 1);if (szpFileData == NULL){fclose(pfile);pfile = NULL;return "";}memset(szpFileData, 0, fileLen + 1);fread(szpFileData, fileLen, 1, pfile);fclose(pfile);strData = DecryptText(szpFileData, cszpKey);return strData;}。
AES加密算法实现C/S模式的通信设计任务:掌握AES的加密算法原理;掌握用socket编程实现C/S模式的加密通信。
设计内容:Socket编程实现客户端和服务器模式的通信;编程实现AES加解密的过程;将AES应用在C/S的通信中,对信息进行加密传输。
设计原理:1、socket编程实现C/S模式的通信,当用户在客户端发出请求时,会在服务器端做出相应的反应,并给出应答信息返回给客户端。
2、AES――对称密码新标准:高级加密标准。
对称密码体制的发展趋势将以分组密码为重点。
分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成。
密钥扩展算法将b字节用户主密钥扩展成r个子密钥。
加密算法由一个密码学上的弱函数f与r个子密钥迭代r次组成。
混乱和密钥扩散是分组密码算法设计的基本原则。
抵御已知明文的差分和线性攻击,可变长密钥和分组是该体制的设计要点。
AES是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准。
AES的基本要求是,采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。
1998年NIST开始AES第一轮分析、测试和征集,共产生了15个候选算法。
1999年3月完成了第二轮AES 2的分析、测试。
最终将Rijndael数据加密算法作为高级加密标准AES。
在应用方面,尽管DES在安全上是脆弱的,但由于快速DES芯片的大量生产,使得DES仍能暂时继续使用,为提高安全强度,通常使用独立密钥的三级DES。
但是DES迟早要被AES代替。
3、AES的主要算法原理:AES 算法是基于置换和代替的。
置换是数据的重新排列,而代替是用一个单元数据替换另一个。
AES 使用了几种不同的技术来实现置换和替换。
为了阐明这些技术,让我们用 Figure 1 所示的数据讨论一个具体的 AES 加密例子。
下面是你要加密的128位值以及它们对应的索引数组:00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15192位密钥的值是:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 170 1 2 3 4 5 6 7 8 9 10 1112 13 14 15 16 17 18 19 20 21 22 23Figure 2 S-盒( Sbox )当 AES 的构造函数(constructor)被调用时,用于加密方法的两个表被初始化。
#define BPOLY 0x1b //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).#define BLOCKSIZE 16 //!< Block size in number of bytes.#define KEY_COUNT 3#if KEY_COUNT == 1#define KEYBITS 128 //!< Use AES128.#elif KEY_COUNT == 2#define KEYBITS 192 //!< Use AES196.#elif KEY_COUNT == 3#define KEYBITS 256 //!< Use AES256.#else#error Use 1, 2 or 3 keys!#endif#if KEYBITS == 128#define ROUNDS 10 //!< Number of rounds.#define KEYLENGTH 16 //!< Key length in number of bytes.#elif KEYBITS == 192#define ROUNDS 12 //!< Number of rounds.#define KEYLENGTH 24 //!< // Key length in number of bytes.#elif KEYBITS == 256#define ROUNDS 14 //!< Number of rounds.#define KEYLENGTH 32 //!< Key length in number of bytes.#else#error Key must be 128, 192 or 256 bits!#endif#define EXPANDED_KEY_SIZE (BLOCKSIZE * (ROUNDS+1)) //!< 176, 208 or 240 bytes.unsigned char AES_Key_Table[32] ={0xd0, 0x94, 0x3f, 0x8c, 0x29, 0x76, 0x15, 0xd8,0x20, 0x40, 0xe3, 0x27, 0x45, 0xd8, 0x48, 0xad,0xea, 0x8b, 0x2a, 0x73, 0x16, 0xe9, 0xb0, 0x49,0x45, 0xb3, 0x39, 0x28, 0x0a, 0xc3, 0x28, 0x3c,};unsigned char block1[256]; //!< Workspace 1.unsigned char block2[256]; //!< Worksapce 2.unsigned char tempbuf[256];unsigned char *powTbl; //!< Final location of exponentiation lookup table.unsigned char *logTbl; //!< Final location of logarithm lookup table. unsigned char *sBox; //!< Final location of s-box.unsigned char *sBoxInv; //!< Final location of inverse s-box. unsigned char *expandedKey; //!< Final location of expanded key.void CalcPowLog(unsigned char *powTbl, unsigned char *logTbl) {unsigned char i = 0;unsigned char t = 1;do {// Use 0x03 as root for exponentiation and logarithms.powTbl[i] = t;logTbl[t] = i;i++;// Muliply t by 3 in GF(2^8).t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0);}while( t != 1 ); // Cyclic properties ensure that i < 255.powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc.}void CalcSBox( unsigned char * sBox ){unsigned char i, rot;unsigned char temp;unsigned char result;// Fill all entries of sBox[].i = 0;do {//Inverse in GF(2^8).if( i > 0 ){temp = powTbl[ 255 - logTbl[i] ];}else{temp = 0;}// Affine transformation in GF(2).result = temp ^ 0x63; // Start with adding a vector in GF(2).for( rot = 0; rot < 4; rot++ ){// Rotate left.temp = (temp<<1) | (temp>>7);// Add rotated byte in GF(2).result ^= temp;}// Put result in table.sBox[i] = result;} while( ++i != 0 );}void CalcSBoxInv( unsigned char * sBox, unsigned char * sBoxInv ) {unsigned char i = 0;unsigned char j = 0;// Iterate through all elements in sBoxInv using i.do {// Search through sBox using j.do {// Check if current j is the inverse of current i.if( sBox[ j ] == i ){// If so, set sBoxInc and indicate search finished.sBoxInv[ i ] = j;j = 255;}} while( ++j != 0 );} while( ++i != 0 );}void CycleLeft( unsigned char * row ){// Cycle 4 bytes in an array left once.unsigned char temp = row[0];row[0] = row[1];row[1] = row[2];row[2] = row[3];row[3] = temp;}void InvMixColumn( unsigned char * column ){unsigned char r0, r1, r2, r3;r0 = column[1] ^ column[2] ^ column[3];r1 = column[0] ^ column[2] ^ column[3];r2 = column[0] ^ column[1] ^ column[3];r3 = column[0] ^ column[1] ^ column[2];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);r0 ^= column[0] ^ column[1];r1 ^= column[1] ^ column[2];r2 ^= column[2] ^ column[3];r3 ^= column[0] ^ column[3];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);r0 ^= column[0] ^ column[2];r1 ^= column[1] ^ column[3];r2 ^= column[0] ^ column[2];r3 ^= column[1] ^ column[3];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);column[0] ^= column[1] ^ column[2] ^ column[3];r0 ^= column[0];r1 ^= column[0];r2 ^= column[0];r3 ^= column[0];column[0] = r0;column[1] = r1;column[2] = r2;column[3] = r3;}void SubBytes( unsigned char * bytes, unsigned char count ){do {*bytes = sBox[ *bytes ]; // Substitute every byte in state.bytes++;} while( --count );}void InvSubBytesAndXOR( unsigned char * bytes, unsigned char * key, unsigned char count ){do {// *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.*bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed.bytes++;key++;} while( --count );}void InvShiftRows( unsigned char * state ){unsigned char temp;// Note: State is arranged column by column.// Cycle second row right one time.temp = state[ 1 + 3*4 ];state[ 1 + 3*4 ] = state[ 1 + 2*4 ];state[ 1 + 2*4 ] = state[ 1 + 1*4 ];state[ 1 + 1*4 ] = state[ 1 + 0*4 ];state[ 1 + 0*4 ] = temp;// Cycle third row right two times.temp = state[ 2 + 0*4 ];state[ 2 + 0*4 ] = state[ 2 + 2*4 ];state[ 2 + 2*4 ] = temp;temp = state[ 2 + 1*4 ];state[ 2 + 1*4 ] = state[ 2 + 3*4 ];state[ 2 + 3*4 ] = temp;// Cycle fourth row right three times, ie. left once.temp = state[ 3 + 0*4 ];state[ 3 + 0*4 ] = state[ 3 + 1*4 ];state[ 3 + 1*4 ] = state[ 3 + 2*4 ];state[ 3 + 2*4 ] = state[ 3 + 3*4 ];state[ 3 + 3*4 ] = temp;}void InvMixColumns( unsigned char * state ){InvMixColumn( state + 0*4 );InvMixColumn( state + 1*4 );InvMixColumn( state + 2*4 );InvMixColumn( state + 3*4 );}void XORBytes( unsigned char * bytes1, unsigned char * bytes2, unsigned char count ) {do {*bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.bytes1++;bytes2++;} while( --count );}void CopyBytes( unsigned char * to, unsigned char * from, unsigned char count ) {do {*to = *from;to++;from++;} while( --count );}void KeyExpansion( unsigned char * expandedKey ){unsigned char temp[4];unsigned char i;unsigned char Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant.unsigned char * key = AES_Key_Table;// Copy key to start of expanded key.i = KEYLENGTH;do {*expandedKey = *key;expandedKey++;key++;} while( --i );// Prepare last 4 bytes of key in temp.expandedKey -= 4;temp[0] = *(expandedKey++);temp[1] = *(expandedKey++);temp[2] = *(expandedKey++);temp[3] = *(expandedKey++);// Expand key.i = KEYLENGTH;while( i < BLOCKSIZE*(ROUNDS+1) ){// Are we at the start of a multiple of the key size?if( (i % KEYLENGTH) == 0 ){CycleLeft( temp ); // Cycle left once.SubBytes( temp, 4 ); // Substitute each byte.XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).*Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);}// Keysize larger than 24 bytes, ie. larger that 192 bits?#if KEYLENGTH > 24// Are we right past a block size?else if( (i % KEYLENGTH) == BLOCKSIZE ) {SubBytes( temp, 4 ); // Substitute each byte.}#endif// Add bytes in GF(2) one KEYLENGTH away.XORBytes( temp, expandedKey - KEYLENGTH, 4 );// Copy result to current 4 bytes.*(expandedKey++) = temp[ 0 ];*(expandedKey++) = temp[ 1 ];*(expandedKey++) = temp[ 2 ];*(expandedKey++) = temp[ 3 ];i += 4; // Next 4 bytes.}}void InvCipher( unsigned char * block, unsigned char * expandedKey ) {unsigned char round = ROUNDS-1;expandedKey += BLOCKSIZE * ROUNDS;XORBytes( block, expandedKey, 16 );expandedKey -= BLOCKSIZE;do {InvShiftRows( block );InvSubBytesAndXOR( block, expandedKey, 16 );expandedKey -= BLOCKSIZE;InvMixColumns( block );} while( --round );InvShiftRows( block );InvSubBytesAndXOR( block, expandedKey, 16 );}void aesDecInit(void){powTbl = block1;logTbl = block2;CalcPowLog( powTbl, logTbl );sBox = tempbuf;CalcSBox( sBox );expandedKey = block1;KeyExpansion( expandedKey );sBoxInv = block2; // Must be block2.CalcSBoxInv( sBox, sBoxInv );}void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock ) {unsigned char temp[ BLOCKSIZE ];CopyBytes( temp, buffer, BLOCKSIZE );InvCipher( buffer, expandedKey );XORBytes( buffer, chainBlock, BLOCKSIZE );CopyBytes( chainBlock, temp, BLOCKSIZE );}unsigned char Multiply( unsigned char num, unsigned char factor ){unsigned char mask = 1;unsigned char result = 0;while( mask != 0 ){// Check bit of factor given by mask.if( mask & factor ){// Add current multiple of num in GF(2).result ^= num;}// Shift mask to indicate next bit.mask <<= 1;// Double num.num = (num << 1) ^ (num & 0x80 ? BPOLY : 0);}return result;}unsigned char DotProduct( unsigned char * vector1, unsigned char * vector2 ) {unsigned char result = 0;result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1 , *vector2 );return result;}void MixColumn( unsigned char * column ){unsigned char row[8] = {0x02, 0x03, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01};// Prepare first row of matrix twice, to eliminate need for cycling.unsigned char result[4];// Take dot products of each matrix row and the column vector.result[0] = DotProduct( row+0, column );result[1] = DotProduct( row+3, column );result[2] = DotProduct( row+2, column );result[3] = DotProduct( row+1, column );// Copy temporary result to original column.column[0] = result[0];column[1] = result[1];column[2] = result[2];column[3] = result[3];}void MixColumns( unsigned char * state ){MixColumn( state + 0*4 );MixColumn( state + 1*4 );MixColumn( state + 2*4 );MixColumn( state + 3*4 );}void ShiftRows( unsigned char * state ){unsigned char temp;// Note: State is arranged column by column.// Cycle second row left one time.temp = state[ 1 + 0*4 ];state[ 1 + 0*4 ] = state[ 1 + 1*4 ];state[ 1 + 1*4 ] = state[ 1 + 2*4 ];state[ 1 + 2*4 ] = state[ 1 + 3*4 ];state[ 1 + 3*4 ] = temp;// Cycle third row left two times.temp = state[ 2 + 0*4 ];state[ 2 + 0*4 ] = state[ 2 + 2*4 ];state[ 2 + 2*4 ] = temp;temp = state[ 2 + 1*4 ];state[ 2 + 1*4 ] = state[ 2 + 3*4 ];state[ 2 + 3*4 ] = temp;// Cycle fourth row left three times, ie. right once.temp = state[ 3 + 3*4 ];state[ 3 + 3*4 ] = state[ 3 + 2*4 ];state[ 3 + 2*4 ] = state[ 3 + 1*4 ];state[ 3 + 1*4 ] = state[ 3 + 0*4 ];state[ 3 + 0*4 ] = temp;}void Cipher( unsigned char * block, unsigned char * expandedKey ) {unsigned char round = ROUNDS-1;XORBytes( block, expandedKey, 16 );expandedKey += BLOCKSIZE;do {SubBytes( block, 16 );ShiftRows( block );MixColumns( block );XORBytes( block, expandedKey, 16 );expandedKey += BLOCKSIZE;} while( --round );SubBytes( block, 16 );ShiftRows( block );XORBytes( block, expandedKey, 16 );}void aesEncInit(void){powTbl = block1;logTbl = tempbuf;CalcPowLog( powTbl, logTbl );sBox = block2;CalcSBox( sBox );expandedKey = block1;KeyExpansion( expandedKey );}void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock ) {XORBytes( buffer, chainBlock, BLOCKSIZE );Cipher( buffer, expandedKey );CopyBytes( chainBlock, buffer, BLOCKSIZE );}#include <string.h>void AES_Test(void){unsigned char dat[16]="0123456789ABCDEF";unsigned char chainCipherBlock[16];unsigned char i;for(i=0;i<32;i++) AES_Key_Table[i]=i;//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。
AES加密C语言实现代码以下是一个简单的C语言实现AES加密算法的代码:```c#include <stdio.h>#include <stdlib.h>#include <stdint.h>//定义AES加密的轮数#define NR 10//定义AES加密的扩展密钥长度#define Nk 4//定义AES加密的行数和列数#define Nb 4//定义AES加密的状态矩阵typedef uint8_t state_t[4][4];//定义AES加密的S盒变换表static const uint8_t sbox[256] =//S盒变换表};//定义AES加密的轮常量表static const uint8_t Rcon[11] =//轮常量表};//定义AES加密的密钥扩展变换函数void KeyExpansion(const uint8_t* key, uint8_t* expandedKey) uint32_t* ek = (uint32_t*)expandedKey;uint32_t temp;//密钥拷贝到扩展密钥中for (int i = 0; i < Nk; i++)ek[i] = (key[4 * i] << 24) , (key[4 * i + 1] << 16) ,(key[4 * i + 2] << 8) , (key[4 * i + 3]);}//扩展密钥生成for (int i = Nk; i < Nb * (NR + 1); i++)temp = ek[i - 1];if (i % Nk == 0)//对上一个密钥的字节进行循环左移1位temp = (temp >> 8) , ((temp & 0xFF) << 24);//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];// 取轮常量Rcontemp = temp ^ (Rcon[i / Nk - 1] << 24);} else if (Nk > 6 && i % Nk == 4)//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];}//生成下一个密钥ek[i] = ek[i - Nk] ^ temp;}//定义AES加密的字节替换函数void SubBytes(state_t* state)for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[i][j] = sbox[(*state)[i][j]];}}//定义AES加密的行移位函数void ShiftRows(state_t* state) uint8_t temp;//第2行循环左移1位temp = (*state)[1][0];(*state)[1][0] = (*state)[1][1]; (*state)[1][1] = (*state)[1][2]; (*state)[1][2] = (*state)[1][3]; (*state)[1][3] = temp;//第3行循环左移2位temp = (*state)[2][0];(*state)[2][0] = (*state)[2][2]; (*state)[2][2] = temp;temp = (*state)[2][1];(*state)[2][1] = (*state)[2][3]; (*state)[2][3] = temp;//第4行循环左移3位temp = (*state)[3][0];(*state)[3][0] = (*state)[3][3];(*state)[3][3] = (*state)[3][2];(*state)[3][2] = (*state)[3][1];(*state)[3][1] = temp;//定义AES加密的列混淆函数void MixColumns(state_t* state)uint8_t temp, tmp, tm;for (int i = 0; i < 4; i++)tmp = (*state)[i][0];tm = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;temp = (*state)[i][0] ^ (*state)[i][1];(*state)[i][0] ^= temp ^ tm;temp = (*state)[i][1] ^ (*state)[i][2];(*state)[i][1] ^= temp ^ tm;temp = (*state)[i][2] ^ (*state)[i][3];(*state)[i][2] ^= temp ^ tm;temp = (*state)[i][3] ^ tmp;(*state)[i][3] ^= temp ^ tm;}//定义AES加密的轮密钥加函数void AddRoundKey(state_t* state, const uint8_t* roundKey) for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] ^= roundKey[i * 4 + j];}}//定义AES加密函数void AES_Encrypt(const uint8_t* plainText, const uint8_t* key, uint8_t* cipherText)state_t* state = (state_t*)cipherText;uint8_t expandedKey[4 * Nb * (NR + 1)];//密钥扩展KeyExpansion(key, expandedKey);//初始化状态矩阵for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] = plainText[i * 4 + j];}}//第1轮密钥加AddRoundKey(state, key);//迭代执行第2至第10轮加密for (int round = 1; round < NR; round++) SubBytes(state);ShiftRows(state);MixColumns(state);AddRoundKey(state, expandedKey + round * 16); }//执行第11轮加密SubBytes(state);ShiftRows(state);AddRoundKey(state, expandedKey + NR * 16);int maiuint8_t plainText[16] =//明文数据};uint8_t key[16] =//密钥数据};uint8_t cipherText[16];AES_Encrypt(plainText, key, cipherText);。
aes算法c语言实现AES(Advanced Encryption Standard)是一种广泛应用于数据加密的算法。
以下是一个使用C语言实现的AES加密算法示例,用于对字符串进行加密和解密。
这个实现是基于ECB模式的,这是一种常用的加密模式,因为它简单且易于实现。
注意:这个实现是为了教学目的而提供的,可能不适合用于生产环境。
生产环境中的加密实现通常需要更复杂和安全的方法。
```c #include <stdio.h> #include <string.h> #include <stdint.h> #include <openssl/aes.h>void AES_encrypt(const uint8_t *key, const uint8_t*plaintext, uint8_t *ciphertext) { AES_KEY aesKey; AES_set_encrypt_key(key, 128, &aesKey);AES_encrypt(plaintext, ciphertext, &aesKey); }void AES_decrypt(const uint8_t *key, const uint8_t*ciphertext, uint8_t *plaintext) { AES_KEY aesKey; AES_set_decrypt_key(key, 128, &aesKey);AES_decrypt(ciphertext, plaintext, &aesKey); }int main() { // 定义密钥和明文/密文缓冲区uint8_t key[AES_BLOCK_SIZE]; // AES_BLOCK_SIZE是AES算法的块大小,通常是16字节(128位) uint8_tplaintext[AES_BLOCK_SIZE], ciphertext[AES_BLOCK_SIZE];// 填充密钥和明文/密文缓冲区 // 这里省略了填充代码,因为在实际应用中,你应该使用合适的填充方案来保护数据的完整性。
基于C语⾔实现的aes256加密算法⽰例本⽂实例讲述了基于C语⾔实现的aes256加密算法。
分享给⼤家供⼤家参考,具体如下:aes256.h:#ifndef uint8_t#define uint8_t unsigned char#endif#ifdef __cplusplusextern "C" {#endiftypedef struct {uint8_t key[32];uint8_t enckey[32];uint8_t deckey[32];} aes256_context;void aes256_init(aes256_context *, uint8_t * );void aes256_done(aes256_context *);void aes256_encrypt_ecb(aes256_context *, uint8_t * );void aes256_decrypt_ecb(aes256_context *, uint8_t * );#ifdef __cplusplus}#endifaes256.c:#include "aes256.h"#define F(x) (((x)<<1) ^ ((((x)>>7) & 1) * 0x1b))#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))// #define BACK_TO_TABLES#ifdef BACK_TO_TABLESconst uint8_t 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};const uint8_t sboxinv[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};#define rj_sbox(x) sbox[(x)]#define rj_sbox_inv(x) sboxinv[(x)]#elseuint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3{uint8_t atb = 1, z;while (x--) {z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;} return atb;}uint8_t gf_log(uint8_t x) // calculate logarithm gen 3{uint8_t atb = 1, i = 0, z;do {if (atb == x) break;z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;} while (++i > 0);return i;}uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse{return (x) ? gf_alog(255 - gf_log(x)) : 0;}uint8_t rj_sbox(uint8_t x){uint8_t y, sb;sb = y = gf_mulinv(x);y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;return (sb ^ 0x63);}uint8_t rj_sbox_inv(uint8_t x){uint8_t y, sb;y = x ^ 0x63;sb = y = (y<<1)|(y>>7);y = (y<<2)|(y>>6); sb ^= y; y = (y<<3)|(y>>5); sb ^= y;return gf_mulinv(sb);}#endifuint8_t rj_xtime(uint8_t x){return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);}void aes_subBytes(uint8_t *buf){register uint8_t i = 16;while (i--) buf[i] = rj_sbox(buf[i]);}void aes_subBytes_inv(uint8_t *buf){register uint8_t i = 16;while (i--) buf[i] = rj_sbox_inv(buf[i]);}void aes_addRoundKey(uint8_t *buf, uint8_t *key){register uint8_t i = 16;while (i--) buf[i] ^= key[i];}void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk){register uint8_t i = 16;while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16+i] = key[16 + i];}void aes_shiftRows(uint8_t *buf){register uint8_t i, j;i = buf[1]; buf[1] = buf[5]; buf[5] = buf[9]; buf[9] = buf[13]; buf[13] = i;i = buf[10]; buf[10] = buf[2]; buf[2] = i;j = buf[3]; buf[3] = buf[15]; buf[15] = buf[11]; buf[11] = buf[7]; buf[7] = j; j = buf[14]; buf[14] = buf[6]; buf[6] = j;}void aes_shiftRows_inv(uint8_t *buf){register uint8_t i, j;i = buf[1]; buf[1] = buf[13]; buf[13] = buf[9]; buf[9] = buf[5]; buf[5] = i;i = buf[2]; buf[2] = buf[10]; buf[10] = i;j = buf[3]; buf[3] = buf[7]; buf[7] = buf[11]; buf[11] = buf[15]; buf[15] = j; j = buf[6]; buf[6] = buf[14]; buf[14] = j;}void aes_mixColumns(uint8_t *buf){register uint8_t i, a, b, c, d, e;for (i = 0; i < 16; i += 4){a = buf[i];b = buf[i + 1];c = buf[i + 2];d = buf[i + 3];e = a ^ b ^ c ^ d;buf[i] ^= e ^ rj_xtime(a^b); buf[i+1] ^= e ^ rj_xtime(b^c);buf[i+2] ^= e ^ rj_xtime(c^d); buf[i+3] ^= e ^ rj_xtime(d^a);}}void aes_mixColumns_inv(uint8_t *buf){register uint8_t i, a, b, c, d, e, x, y, z;for (i = 0; i < 16; i += 4){a = buf[i];b = buf[i + 1];c = buf[i + 2];d = buf[i + 3];e = a ^ b ^ c ^ d;z = rj_xtime(e);x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));buf[i] ^= x ^ rj_xtime(a^b); buf[i+1] ^= y ^ rj_xtime(b^c);buf[i+2] ^= x ^ rj_xtime(c^d); buf[i+3] ^= y ^ rj_xtime(d^a);}}void aes_expandEncKey(uint8_t *k, uint8_t *rc){register uint8_t i;k[0] ^= rj_sbox(k[29]) ^ (*rc);k[1] ^= rj_sbox(k[30]);k[2] ^= rj_sbox(k[31]);k[3] ^= rj_sbox(k[28]);*rc = F( *rc);for(i = 4; i < 16; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];k[16] ^= rj_sbox(k[12]);k[17] ^= rj_sbox(k[13]);k[18] ^= rj_sbox(k[14]);k[19] ^= rj_sbox(k[15]);for(i = 20; i < 32; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];}void aes_expandDecKey(uint8_t *k, uint8_t *rc){uint8_t i;for(i = 28; i > 16; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];k[16] ^= rj_sbox(k[12]);k[17] ^= rj_sbox(k[13]);k[18] ^= rj_sbox(k[14]);k[19] ^= rj_sbox(k[15]);for(i = 12; i > 0; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];*rc = FD(*rc);k[0] ^= rj_sbox(k[29]) ^ (*rc);k[1] ^= rj_sbox(k[30]);k[2] ^= rj_sbox(k[31]);k[3] ^= rj_sbox(k[28]);}void aes256_init(aes256_context *ctx, uint8_t *k){uint8_t rcon = 1;register uint8_t i;for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];for (i = 8;--i;) aes_expandEncKey(ctx->deckey, &rcon);}void aes256_done(aes256_context *ctx){register uint8_t i;for (i = 0; i < sizeof(ctx->key); i++)ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;}void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf){uint8_t i, rcon;aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);for(i = 1, rcon = 1; i < 14; ++i){aes_subBytes(buf);aes_shiftRows(buf);aes_mixColumns(buf);if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key); }aes_subBytes(buf);aes_shiftRows(buf);aes_expandEncKey(ctx->key, &rcon);aes_addRoundKey(buf, ctx->key);}void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf){uint8_t i, rcon;aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);aes_shiftRows_inv(buf);aes_subBytes_inv(buf);for (i = 14, rcon = 0x80; --i;){if( ( i & 1 ) ){aes_expandDecKey(ctx->key, &rcon);aes_addRoundKey(buf, &ctx->key[16]);}else aes_addRoundKey(buf, ctx->key);aes_mixColumns_inv(buf);aes_shiftRows_inv(buf);aes_subBytes_inv(buf);}aes_addRoundKey( buf, ctx->key);}demo.c:#include#include#include "aes256.h"#define DUMP(s, i, buf, sz) {printf(s); /for (i = 0; i < (sz);i++) /printf("x ", buf[i]); /printf("/n");}int main (int argc, char *argv[]){aes256_context ctx;uint8_t key[32];uint8_t buf[16], i;for (i = 0; i < sizeof(buf);i++) buf[i] = i * 16 + i;for (i = 0; i < sizeof(key);i++) key[i] = i;DUMP("txt: ", i, buf, sizeof(buf));DUMP("key: ", i, key, sizeof(key));printf("---/n");aes256_init(&ctx, key);aes256_encrypt_ecb(&ctx, buf);DUMP("enc: ", i, buf, sizeof(buf));printf("tst: 8e a2 b7 ca 51 67 45 bf ea fc 49 90 4b 49 60 89/n");aes256_init(&ctx, key);aes256_decrypt_ecb(&ctx, buf);DUMP("dec: ", i, buf, sizeof(buf));aes256_done(&ctx);return 0;}PS:关于加密解密感兴趣的朋友还可以参考本站在线⼯具:希望本⽂所述对⼤家C语⾔程序设计有所帮助。
C语言实现AES加密解密AES(Advanced Encryption Standard)是一种对称加密算法,它是目前广泛使用的加密标准之一、本文将介绍如何使用C语言实现AES加密和解密。
AES算法使用128位(16字节)的块进行加密和解密。
它支持128位、192位和256位长度的密钥。
在下面的示例中,我们将演示如何使用128位的密钥进行AES加密和解密。
首先,我们需要准备一个AES加密所需的密钥。
我们可以通过一个字符串来表示密钥,然后将其转换为字节数组。
在C语言中,可以使用`strncpy`函数将字符串复制到字节数组中。
```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/aes.h>#define AES_KEY_SIZE 128int mai//准备AES密钥unsigned char key[AES_KEY_SIZE/8];strncpy((char*)key, keyStr, AES_KEY_SIZE/8);//创建AES加密上下文AES_KEY aesKey;AES_set_encrypt_key(key, AES_KEY_SIZE, &aesKey); //待加密的数据unsigned char input[] = "Hello, AES!";int inputLen = sizeof(input)/sizeof(input[0]); //加密数据unsigned char encrypted[AES_BLOCK_SIZE];AES_encrypt(input, encrypted, &aesKey);//输出加密结果printf("Encrypted: ");for (int i = 0; i < AES_BLOCK_SIZE; i++)printf("%02x", encrypted[i]);}printf("\n");//创建AES解密上下文AES_set_decrypt_key(key, AES_KEY_SIZE, &aesKey); //解密数据unsigned char decrypted[AES_BLOCK_SIZE];AES_decrypt(encrypted, decrypted, &aesKey);//输出解密结果printf("Decrypted: ");for (int i = 0; i < AES_BLOCK_SIZE; i++)printf("%c", decrypted[i]);}printf("\n");return 0;```在上面的示例中,我们使用OpenSSL库提供的AES函数来执行加密和解密操作。
c++代码基于aes算法的加解密系统设计与实现查阅资料深入了解aes算法的加解密原理1. 引言1.1 概述本文主要介绍了基于AES(Advanced Encryption Standard)算法的加解密系统的设计和实现。
AES算法是一种对称加密算法,被广泛应用于数据保护领域,具有高安全性和强大的加密能力。
通过深入研究AES算法的加解密原理,我们将设计并实现一个完整的加解密系统,以满足对数据安全性要求较高的应用场景。
1.2 文章结构本文分为五个部分,每个部分都围绕着设计与实现一个基于AES算法的加解密系统展开。
首先是引言部分,概述了文章内容的背景和目标;接下来是AES算法介绍部分,主要介绍了AES算法及其在加密过程中的原理;然后是系统设计与实现部分,详细说明了我们采取的设计思路、系统架构以及实现步骤;随后是功能分析和测试结果部分,对系统进行功能需求分析,并展示了系统在不同场景下的功能演示与说明;最后是结论与展望部分,总结文章并提出改进方向。
1.3 目的本文旨在深入探究AES算法及其在加解密过程中所涉及到的技术细节。
通过系统地分析AES算法的原理和过程,我们将能够更好地理解其应用场景,并能够设计并实现一个功能完备、安全可靠的加解密系统。
同时,本文也将对该系统进行功能分析和测试,以评估其性能表现,并总结出系统的优点和不足之处,为未来的改进工作提供指导。
2. AES算法介绍:2.1 历史背景:AES(Advanced Encryption Standard)是一种对称加密算法,由美国国家标准与技术研究所(NIST)于2001年推出。
之前的DES(Data Encryption Standard)算法因为密钥长度过短,安全性较弱,于是出现了需要更高安全性的替代方案,即AES算法。
2.2 加密原理:AES算法采用分组密码方式,将明文划分为固定长度的块,并通过多轮操作进行混淆和替换来实现加密。
它支持三个密钥长度:128位、192位和256位,并根据不同密钥长度进行不同轮数的加密操作。
基于VC的RSA加密与解密实现技术一、RSA基本原理对明文分组M和密文分组C,加密与解密过程如下:C = POW (M , e) mod nM = POW(C , d) mod n = POW(POW( M ,e), d) mod n=POW( M,e*d)其中POW是指数函数,mod是求余数函数。
其中收发双方均已知n,发送放已知e,只有接受方已知d,因此公钥加密算法的公钥为KU={ e , n},私钥为KR={d , n}。
该算法要能用做公钥加密,必须满足下列条件:1. 可以找到e ,d和n,使得对所有M<n ,POW(M ,e*d)=M mod n .2. 对所有M<n,计算POW (M , e)和POW(C , d)是比较容易的。
3. 由e 和n确定d是不可行的下面介绍RSA算法,该算法中到的下列的元素:两个素数p, q (保密的,选定的)n=p*q (公开的,计算得出的)e , gcd ( x(n),e) =1;1<e<x(n) (公开的,选定的)d≡POW(e,-1) mod x(n) (保密的,计算得出的)这里,私钥为{d ,n},公钥为{e ,n}。
假定用户A已公布了其公钥,用户B要发送消息M给A,那么用户B计算C= POW (M , e) mod n,并发送C,在接受端,用户A计算M = POW(C , d) mod n 以解出消息M。
二、开发平台及语言1、开发平台:Microsoft V isual Studio c++ 6.02.语言:c++三、应用程序界面设计及变量的连接和方法的名称对象ID Caption 连接变量或方法成组框IDC_STA TIC 产生密钥过程无编辑框IDC_PRIME_EDIT1 无m_PrimeEdit1/long编辑框IDC_PRIME_EDIT2 无m_PrimeEdit2/long编辑框IDC_PUBN_EDIT 无m_PubNEdit/long编辑框IDC_PUBX_EDIT 无m_PubXEdit/long编辑框IDC_PUBKEY_EDI 无m_PubKeyEdit/long编辑框IDC_PRIKEY_EDIT 无m_PriKeyEdit/CEdit命令按钮IDC_CALCULA TE_BUTTON 计算OnCalculateButton()命令按钮IDC_PUBKEY_BUTTON 公有密钥OnPubkeyButton()命令按钮IDC_PRIKEY_BUTTON 私有密钥OnPrikeyButton()命令按钮IDC_HIDE_PRIKEY_BUTTON 隐藏私钥OnHidePrikeyButton()命令按钮IDC_SHOW_PRIKEY_BUTTON 显示私钥OnShowPrikeyButton()命令按钮IDC_STA TIC 加密和解密过程无编辑框IDC_RESOURCE_EDIT 无m_ResourceEdit/CEditOnChangeResourceEdit()编辑框IDC_CRYPTOGRAPH_EDIT 无m_CryptographEdit/CEdit编辑框IDC_OPEN_EDIT 无m_OpenEdit/CEdit编辑框IDC_LINE 无m_Line/CEdit编辑框IDC_CHAR 无m_Char/CEdit命令按钮IDC_ENCRYPT_BUTTON 数字加密OnEncryptButton()命令按钮IDC_OPEN_BUTTON 数字解密OnOpenButton()命令按钮IDC_CLEAR_BUTTON Clear OnClearButton()命令按钮IDC_EXIT_BUTTON Exit OnExitButton()命令按钮IDC_ENCRYPT_TEXT_BUTTON 文本加密OnEncryptTextButton()命令按钮IDC_OPEN_TEXTBUTTON 文本解密OnOpenTextbutton()菜单ID_CALCULA TE_MENU 计算OnCalculateMenu()菜单ID_PUBKEY_MENU 公有密钥OnPubkeyMenu()菜单ID_PRIKEY_MENU 私有密钥OnPrikeyMenu()菜单ID_HIDE_MENU 隐藏私钥OnHideMenu()菜单ID_SHOW_MENU 显示私钥OnShowMenu()菜单ID_CLEAR_MENU 清除OnClearMenu()菜单ID_EXIT_MENU 退出OnExitMenu()菜单ID_ENCRYPTNUM_MENU 数字加密OnEncryptnumMenu()菜单ID_OPENNUM_MENU 数字解密OnOpennumMenu()菜单ID_ENCRYPTTEXT_MENU 文本加密OnEncrypttextMenu()菜单ID_OPENTEXT_MENU 文本解密OnOpentextMenu()菜单ID_ABOUT_MENU 关于OnAboutMenu()四、RSADlg.h声明// RSADlg.h : header file#if !defined(AFX_RSADLG_H__D491C4A6_0DE9_4430_BE31_2150D1C5E35F__INCLUDE D_)#define AFX_RSADLG_H__D491C4A6_0DE9_4430_BE31_2150D1C5E35F__INCLUDED_ #if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <math.h>/////////////////////////////////////////////////////////////////// CRSADlg dialogclass CRSADlg : public CDialog{// Constructionpublic:char CalculateModOfChar(double num1, double num2);char CalculateModOfChar(const char cChar, double num,long *ps);double calculatemod(double num1, double num2);int primeNumber(long m);CRSADlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DA TA(CRSADlg)enum { IDD = IDD_RSA_DIALOG };CEdit m_OpenEdit;CEdit m_CryptographEdit;CEdit m_PriKeyEdit;CEdit m_ResourceEdit;CEdit m_Line;CEdit m_Char;long m_PubNEdit;long m_PubXEdit;long m_PrimeEdit1;long m_PrimeEdit2;long m_PubKeyEdit;//}}AFX_DA TA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CRSADlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CRSADlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnCalculateButton();afx_msg void OnPubkeyButton();afx_msg void OnPrikeyButton();afx_msg void OnChangeResourceEdit();afx_msg void OnHidePrikeyButton();afx_msg void OnShowPrikeyButton();afx_msg void OnClearButton();afx_msg void OnExitButton();afx_msg void OnEncryptButton();afx_msg void OnOpenButton();afx_msg void OnEncryptTextButton();afx_msg void OnOpenTextbutton();afx_msg void OnCalculateMenu();afx_msg void OnPubkeyMenu();afx_msg void OnPrikeyMenu();afx_msg void OnHideMenu();afx_msg void OnShowMenu();afx_msg void OnClearMenu();afx_msg void OnExitMenu();afx_msg void OnEncryptnumMenu();afx_msg void OnOpennumMenu();afx_msg void OnEncrypttextMenu();afx_msg void OnOpentextMenu();afx_msg void OnAboutMenu();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:long lArrayOfCount[300]; //文本加密和解密过程中记数功能};//{{AFX_INSERT_LOCA TION}}// Microsoft V isual C++ will insert additional declarations immediately before the previous line. #endif// !defined(AFX_RSADLG_H__D491C4A6_0DE9_4430_BE31_2150D1C5E35F__INCLUDED _)五、映射消息的应用程序代码1、void CRSADlg::OnCalculateButton() //计算按钮处理函数{UpdateData(TRUE);int flag1,flag2;flag1=primeNumber(m_PrimeEdit1);flag2=primeNumber(m_PrimeEdit2);if(flag1==1)m_PrimeEdit1=m_PrimeEdit1;else m_PrimeEdit1=0;if(flag2==1)m_PrimeEdit2=m_PrimeEdit2;else m_PrimeEdit2=0;m_PubNEdit=m_PrimeEdit1*m_PrimeEdit2;m_PubXEdit=(m_PrimeEdit1-1)*(m_PrimeEdit2-1);UpdateData(FALSE);}2、int CRSADlg::primeNumber(long m) //判断是否为素数{int flag=1;long temp=(long)sqrt(m);for(int i=2;i<=temp;i++){if(m%i==0){flag=0;break;}}if(flag==0) return 0;else return 1;}3、void CRSADlg::OnPubkeyButton() //公有密钥按钮处理函数{UpdateData(TRUE);if(primeNumber(m_PubKeyEdit)==0||m_PubXEdit%m_PubKeyEdit==0||m_PubKeyEdit>m_Pub XEdit)m_PubKeyEdit=0;UpdateData(FALSE);}4、void CRSADlg::OnPrikeyButton(){UpdateData(TRUE);double privatenum;char cBuffer[32];for(double i=1; ;i++){double temp=fmod((i*m_PubXEdit+1),m_PubKeyEdit);if(temp==0.0 && (i*m_PubXEdit+1)/m_PubKeyEdit<m_PubXEdit){privatenum=(i*m_PubXEdit+1)/m_PubKeyEdit;break;}}sprintf(cBuffer,"%0.0f",privatenum);m_PriKeyEdit.SetWindowText(cBuffer);}5、void CRSADlg::OnChangeResourceEdit(){CString METext;char Count[10];int nCharNum,nLineNum;m_ResourceEdit.GetWindowText(METext);nCharNum=METext.GetLength();nLineNum=m_ResourceEdit.GetLineCount();nCharNum-=(nLineNum-1);itoa(nCharNum,Count,10);m_Char.SetWindowText(Count);itoa(nLineNum,Count,10);m_Line.SetWindowText(Count);}6、void CRSADlg::OnHidePrikeyButton(){m_PriKeyEdit.ShowWindow(SW_HIDE);}8、void CRSADlg::OnExitButton(){OnOK();}9、void CRSADlg::OnOpenButton() //数字解密按钮处理函数{char sArray[20];char Count[32];double number1,number2;double nPriKey;m_PriKeyEdit.GetWindowText(sArray,20);nPriKey=atof((LPCTSTR)sArray);m_CryptographEdit.GetWindowText(sArray,20);number1=atof((LPCTSTR)sArray);number2=calculatemod(number1,nPriKey);sprintf(Count,"%0.0f",number2);m_OpenEdit.SetWindowText(Count);}10、double CRSADlg::calculatemod(double num1, double num2) //数字加密和解密算法{ //求余处理函数double mul=1.0;for(long i=0;i<(long)num2;i++){mul*=fmod(num1,m_PubNEdit);mul=fmod(mul,m_PubNEdit);}mul=fmod(mul,m_PubNEdit);return mul;}11、void CRSADlg::OnEncryptTextButton(){long *point=lArrayOfCount;CString sArray;int nCount;m_Char.GetWindowText(sArray);nCount=atoi(sArray);char sResourceText[300];char sCryptogramText[300];char *pResourceText=sResourceText;char *pCryptogramText=sCryptogramText;m_ResourceEdit.GetWindowText(sResourceText,nCount+1);for(int i=0;i<nCount;i++){*pCryptogramText=CalculateModOfChar(*pResourceText,m_PubKeyEdit,point);//调用文本加密求余函point++; //指向下个地址,准备记录下个数pResourceText++;pCryptogramText++;}*pCryptogramText[nCount]='\0';m_CryptographEdit.SetWindowText(sCryptogramText);}12、void CRSADlg::OnOpenTextbutton(){long *point1=lArrayOfCount;char sArray[10];int nCount;double fPriKey;m_Char.GetWindowText(sArray,10);nCount=atoi((LPCTSTR)sArray);m_PriKeyEdit.GetWindowText(sArray,10);fPriKey=atof((LPCTSTR)sArray);char sOpenText[300];char sCryptogramText[300];char *pOpenText=sOpenText;char *pCryptogramText=sCryptogramText;m_CryptographEdit.GetWindowText(sCryptogramText,300);double tempnumber;for(int i=0;i<nCount;i++){tempnumber=(*point1)*128+*pCryptogramText;*pOpenText=CalculateModOfChar(tempnumber,fPriKey); //调用文本解密求余函数,得到解密字符point1++; //指向记录下个数字pCryptogramText++;pOpenText++;}*pOpenText[nCount]='\0';m_OpenEdit.SetWindowText(sOpenText);}13、char CRSADlg::CalculateModOfChar(const char cChar, double num,long *ps){ //文本加密算法求余处理函数double mul=1;for(long i=0;i<num;i++){mul*=fmod((double)cChar,m_PubNEdit);mul=fmod(mul,m_PubNEdit);}*ps=(long)mul/128;return (char)fmod(mul,128);}14、char CRSADlg::CalculateModOfChar(double num1, double num2){ //文本函数解密处理函数double mul=1;for(long i=0;i<num2;i++){mul*=fmod(num1,m_PubNEdit);mul=fmod(mul,m_PubNEdit);}return (char)mul;}15、void CRSADlg::OnCalculateMenu(){OnCalculateButton();}16、void CRSADlg::OnPubkeyMenu(){OnPubkeyButton();}17、void CRSADlg::OnPrikeyMenu(){OnPrikeyButton();}18、void CRSADlg::OnHideMenu(){OnHidePrikeyButton();}19、void CRSADlg::OnShowMenu(){OnShowPrikeyButton();}20、void CRSADlg::OnClearMenu(){OnClearButton();}21、void CRSADlg::OnExitMenu(){OnExitButton();}22、void CRSADlg::OnEncryptnumMenu(){OnEncryptButton();}23、void CRSADlg::OnOpennumMenu(){OnOpenButton();}24、void CRSADlg::OnEncrypttextMenu(){OnEncryptTextButton();}25、void CRSADlg::OnOpentextMenu(){OnOpenTextbutton();}26、void CRSADlg::OnAboutMenu(){MessageBox("卖石头创作QQ:170758887\n\nRSA V1.0 版权所有(C) 2006\n\nEmail:zero_dian@\n\n\n");}27、void CRSADlg::OnEncryptButton() //数字加密按钮处理函数{char sArray[20];char Count[32];double number1,number2;m_ResourceEdit.GetWindowText(sArray,20);number1=atof((LPCTSTR)sArray);number2=calculatemod(number1,m_PubKeyEdit);//itoa(number2,Count,10);sprintf(Count,"%0.0f",number2);m_CryptographEdit.SetWindowText(Count);}28、void CRSADlg::OnShowPrikeyButton(){m_PriKeyEdit.ShowWindow(SW_SHOW);}29、void CRSADlg::OnClearButton(){m_ResourceEdit.SetSel(0,-1);m_ResourceEdit.ReplaceSel("");m_PriKeyEdit.SetSel(0,-1);m_PriKeyEdit.ReplaceSel("");m_CryptographEdit.SetSel(0,-1);m_CryptographEdit.ReplaceSel("");m_OpenEdit.SetSel(0,-1);m_OpenEdit.ReplaceSel("");UpdateData(FALSE);}本文来自CSDN博客,转载请标明出处:/zero_dian/archive/2006/01/06/572501.aspx。
AES加密解密算法及其在c语言上的实现引言对称密码算法主要用于保证数据的机密性,通信双方在加密/ 解密过程中使用它们共享的单一密钥。
对称密码算法的使用相当广泛,密码学界已经对它们进行了深入的研究[1] 。
最常用的对称密码算法是数据加密标准(DES) 算法,它是由IBM在美国国家安全局(NSA) 授意之下研制的一种使用56 位密钥的分组密码算法。
自1977 年公布成为美国政府的商用加密标准以来已使用20 多年[2] 。
DES 的主要问题是其密钥长度较短,已不适合于当今分布式开放网络对数据加密安全性的要求。
在DES 每隔五年的评估会议中,最后一次在1998 年美国政府终于决定不再继续延用DES作为联邦加密标准,也就表明了DES 将退出加密标准的舞台,而新的标准AES(AdvancedEncryptionStandard ) 将粉墨登场[3] 。
AES是美国国家标准技术研究所NIST旨在取代DES的新一代的加密标准[3~5] 。
NIST对AES候选算法的基本要求是:对称分组密码体制;密钥长度支持128,192,256位;明文分组长度128 位;算法应易于各种硬件和软件实现。
1998年NIST开始AES第一轮征集、分析、测试,共产生了15 个候选算法。
1999 年3 月完成了第二轮AES 的分析、测试。
1999 年8 月NIST公布了五种算法(MARS,RC6,Rijndael,Serpent,Twofish) 成为候选算法。
最后,Rijn2dael[5] ,这个由比利时人设计的算法与其它候选算法在成为高级加密标准(AES) 的竞争中取得成功,于2000 年10月被NIST宣布成为取代DES的新一代的数据加密标准,即AES。
尽管人们对AES还有不同的看法[6~8] ,但总体来说,Rijndael作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。
AES设计有三个密钥长度:128,192,256 比特, 相对而言,AES 的128 比特密钥比DES的56 比特密钥强1021倍[4] 。
基于VC++的AES算法的实现
陶小艳
【期刊名称】《电脑知识与技术》
【年(卷),期】2005(000)009
【摘要】本文重点介绍了高级加密标准算法,在研究分析了AES解密/加密原理的基础上,用VC++语言完整的实现了AES算法.
【总页数】3页(P16-18)
【作者】陶小艳
【作者单位】广州大学松田学院计算机系,广东,广州,511370
【正文语种】中文
【中图分类】TP301
【相关文献】
1.基于粗粒度可重构密码阵列的AES算法映射实现 [J], 李远铭;严迎建;李伟
2.基于密码流处理器的AES算法软件流水实现 [J], 张舜标
3.基于STM32单片机的AES算法优化与实现 [J], 许韫韬;吕志刚;黄义国;李晓艳
4.基于Chen超混沌系统的改进AES算法的实现 [J], 刘海峰;邹丹阳
5.基于AES算法的DSP安全防护设计实现 [J], 张猛华;陈振娇;徐新宇
因版权原因,仅展示原文概要,查看原文内容请购买。
基于VC++的 AES 加密算法实现
摘要:本文对AES 的加密算法作了简单介绍,并且对AES 的加密算法的加密和解密过程中的重要环节给出了简单的c++代码实现。
关键词:AES 加密 1.AES 简介
高级加密标准AES (Advanced Encryption Standard )又称Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。
经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST )于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。
2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一[1]。
明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。
2.AES 加密算法及其c++实现
AES 加密有很多轮的重复和变换。
大致步骤如下:1、密钥扩展(KeyExpansion ),2、初始轮(Initial Round ),3、重复轮(Rounds ),每一轮又包括:SubBytes (字节替代)、ShiftRows (行移位)、MixColumns (列混淆)、AddRoundKey(轮密钥加),4、最终轮(Final Round ),最终轮没有MixColumns 。
2.1 SubBytes (字节替换)
字节替换SubBytes 是一个非线性变换,它将输入状态的每一个字节映射成另一个字节,也称为Rijndael 的S 盒,变换过程如图1所示。
SubBytes 变换过程由以下两个步骤组成。
把每个字节映射为它在有限域()8
2GF 中的乘法逆元,
“0”被映射为它自身。
即对于()8
2
GF f ∈,
求f 的逆元()8
2
GF g ∈,使得:
(
)1
mod 12
48++++≡⋅=⋅x x x x f g g f (式1)
图1subBytes 过程
将上一步得到的乘法逆元记为()01234567x x x x x x x x g =,再对g 作仿射变换:
⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎦⎤
⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡⊕⎥⎥⎥⎥⎥⎥⎥
⎥⎥⎥⎥⎦
⎤
⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
⎥⎦⎤⎢
⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡=⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡0110001111
1
1
1
001111100001111100001111110001111
110001111110001111110001765432107654
3210x x x x x x x x y y
y y y y y
y (式2)
void AES::SubBytes(unsigned char state[][4])
{ intr,c;
for(r=0; r<4; r++) { for(c=0; c<4; c++) { state[r][c] = Sbox[state[r][c]];
}
}
}
2.2ShiftRows (行移位)
ShiftRows 实现状态矩阵行的循环移位操作,变换方法如图2所示,即行移位变换作用在中间态的行上,第0行不动,第1行循环左移1个字节,第2行循环左移2个字节,第3行循环左移3个字节。
No change Shift 1
Shift 2Shift 3
图2shiftRows 的循环移位操作
void AES::ShiftRows(unsigned char state[][4]) { unsigned char t[4]; intr,c;
for(r=1; r<4; r++)
{
for(c=0; c<4; c++)
{ t[c] = state[r][(c+r)%4]; }
for(c=0; c<4; c++) { state[r][c] = t[c];
}
}
}
2.3 MixColumns (列混淆)
MixColumns 实现逐列变换,如图3所示。
图3Mix Columns 变换
首先把状态矩阵每列的4个字节表示为有限域()82GF 上的一个多项式()x a ,再将该多项式与固定的多项式()x c 做模14+x 乘法,即
()()()()
1mod 4
+⋅=x x a x c x b (式3)
其中,()x c {}{}{}{}020101032
3
+++=x x x 。
相乘的积b(x)是一个次数小于4的多项式,将其4个系数作为列混合变换结果对应列的4个字节。
列混合变换可用矩阵表示为:
⎥⎥⎥
⎥⎥⎦
⎤
⎢⎢⎢⎢⎢⎣⎡⋅⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡=⎥⎥⎥⎥⎥⎦
⎤⎢⎢⎢⎢⎢⎣⎡j j j j j j j j a a a a b b b b ,3,2,1,0,3,2,1,00201
01
030302010101
030201
01010302
()3,2,1,0=j 。
(式4)
void AES::MixColumns(unsigned char state[][4]) {
unsigned char t[4];
for(c=0; c< 4; c++) { for(r=0; r<4; r++) { t[r] = state[r][c];
}
for(r=0; r<4; r++) { state[r][c] = FFmul(0x02, t[r]) ^ FFmul(0x03, t[(r+1)%4]) ^ FFmul(0x01, t[(r+2)%4])
^ FFmul(0x01, t[(r+3)%4]);
}
}
}
2.4 AddRoundKey(轮密钥加)
AddRoundKey 用于将中间状态ai,j 与该轮的子密钥字ki,j 进行逐位异或运算,即
()j i j i j i j i j i k a k a y AddRoundke b ,,,,,,⊕==。
(式5)
轮密钥加变换过程如图4所示
图4 AddRoundKey 轮密钥加
void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4]) { intr,c;
for(c=0; c<4; c++) {
for(r=0; r<4; r++)
state[r][c] ^= k[r][c];
}
}
}
3.解密过程
AES解密算法与加密不同,基本运算中除了AddRoundKey(轮密钥加)不变外,其余的都需要进行逆变换,即InvSubBytes(逆字节替代)、InvShiftRows(逆行移位)、InvMixColumns (逆列混淆)。
3.1 InvSubBytes(逆字节替代)
void AES::InvSubBytes(unsigned char state[][4])
{
intr,c;
for(r=0; r<4; r++)
{
for(c=0; c<4; c++)
{
state[r][c] = InvSbox[state[r][c]];
}
}
}
3.2 InvShiftRows(逆行移位)
void AES::InvShiftRows(unsigned char state[][4])
{
unsigned char t[4];
intr,c;
for(r=1; r<4; r++)
{
for(c=0; c<4; c++)
{
t[c] = state[r][(c-r+4)%4];
}
for(c=0; c<4; c++)
{
state[r][c] = t[c];
}
}
}
3.3 InvMixColumns(逆列混淆)
void AES::InvMixColumns(unsigned char state[][4])
{
unsigned char t[4];
intr,c;
for(c=0; c< 4; c++)
{
for(r=0; r<4; r++)
{
t[r] = state[r][c];
}
for(r=0; r<4; r++)
{
state[r][c] = FFmul(0x0e, t[r])
^ FFmul(0x0b, t[(r+1)%4])
^ FFmul(0x0d, t[(r+2)%4])
^ FFmul(0x09, t[(r+3)%4]);
}
}
}
4结束语
本文只是给出了AES的加密过程和解密过程主要的步骤的代码,以上代码并不是一个完整的AES程序,程序的其他部分有待读者自己完成。
参考文献
[1]王文海,蔡红昌密码学理论与营运基础国防工业出版社,2009
[2]卿斯汉密码学与计算机网络安全清华大学出版社2001
[3]范明钰,王光卫密码学理论与技术清华大学出版社2008
[4]【美】Bruce Schneier应用密码学:协议、算法与C源程序机械工业出版社2005。