第一种方式:亲测可直接用,可设置AES128、AES192、AES256。
密匙长度 | AES128是16字节,也就是128bit; AES192是24字节,也就是192bit; AES256是32字节,也就是256bit; |
|
加密轮数 | AES128是10轮; AES192是12轮; AES256是14轮; |
AESAlgorithmMode.h
#ifndef _AESALGORITHMMODE_H_
#define _AESALGORITHMMODE_H_
#define Nb 4 //加解密数据块大小,固定为4
//加密类型对应的密匙长度,单位bit
typedef enum {
AES128 = 128,
AES192 = 192,
AES256 = 256,
} AESType_t;
//加解密模式
typedef enum {
AES_MODE_ECB = 0, // 电子密码本模式
AES_MODE_CBC = 1, // 密码分组链接模式
} AESMode_t;
typedef struct {
int Nk; //用户不需要填充,密钥长度,单位字节, AES128:Nk=16、AES192:Nk=24、AES256:Nr=32
int Nr; //用户不需要填充,加密的轮数 AES128:Nr=10、AES192:Nr=12、AES256:Nr=14
int type;//用户需填充,关联AESType_t
int mode;//用户需填充,关联AESMode_t
const void* key;//用户需填充,密匙
const void* pIV;//用户需填充,初始化向量, 当mode=AES_MODE_CBC时需要设置,指向unsigned char IV[4*Nb];
//AES拓展密匙, 空间大小 AES128:4*Nb*(10+1):4*Nb*(12+1)、AES256:4*Nb*(14+1)
unsigned char expandKey[4 * Nb * (14 + 1)];//用户不需要填充,[4*Nb*(Nr+1)]、这里按最大的AES256进行初始化
} AESInfo_t;
class AESAlgorithm
{
public:
AESAlgorithm():aesInfoP(0) {};
~AESAlgorithm() {};
public:
/*****************************************************************************
* 函数名: AESInit
* 功能描述: 初始化
* 输入参数: aesInfoP -- 用户需要填充
* 输出参数: 无。
* 返回值: 无。
*****************************************************************************/
void AESInit(AESInfo_t* AesInfoP);
/*****************************************************************************
* 函数名: AESEncrypt
* 功能描述: 加密数据
* 输入参数: pPlainText -- 加密前的明文,其长度为nDataLen字节。
* dataLen -- 数据长度,以字节为单位,需要是整倍数,AES128:16倍数、AES192:24倍数、AES256:32倍数。
* 输出参数: pCipherText -- 加密后的密文,预留长度:dataLen+16
* 返回值: 解密后的数据长度。
*****************************************************************************/
unsigned int AESEncrypt(const unsigned char* pPlainText, unsigned char* pCipherText, unsigned int dataLen);
/*****************************************************************************
* 函数名: AESDecrypt
* 功能描述: 解密数据
* 输入参数: pPlainText -- 解密后的明文,其长度为dataLen字节。
* dataLen -- 数据长度,以字节为单位,需要是整倍数,AES128:16倍数、AES192:24倍数、AES256:32倍数。
* 输出参数: pCipherText -- 解密前的密文,可以与pCipherText相同
* 返回值: 返回解密后的数据长度。
*****************************************************************************/
unsigned int AESDecrypt(unsigned char* pPlainText, const unsigned char* pCipherText, unsigned int nDataLen);
private:
void RShiftWord(unsigned char* pWord);
void XorBytes(unsigned char* pData1, const unsigned char* pData2, unsigned char nCount);
void AddKey(unsigned char* pData, const unsigned char* pKey);
void SubstituteBytes(unsigned char* pData, unsigned char dataCnt, const unsigned char* pBox);
void ShiftRows(unsigned char* pState, unsigned char bInvert);
unsigned char GfMultBy02(unsigned char num);
void MixColumns(unsigned char* pData, unsigned char bInvert);
void BlockEncrypt(unsigned char* pData);
void BlockDecrypt(unsigned char* pData);
unsigned int AESAddPKCS7Padding(unsigned char* data, unsigned int len);
unsigned int AESDelPKCS7Padding(unsigned char* pData, unsigned int len);
private:
AESInfo_t* aesInfoP;
};
#endif // _AESALGORITHMMODE_H_
AESAlgorithmMode.cpp
#include "AESAlgorithmMode.h"
#include <string.h>
// GF(2^8) 多项式
#define BPOLY 0x1B //x^4 + x^3 + x^1 + x^0= 从右边开始算,bit0、bit1、bit3、bit4、为1,bit2、bit5、bit6、bit7为0,即00011011=0x1B
/*
SubstituteBytes()
加密时:使用S盒,将待加密数据为S盒索引将加密数据替换为S盒的内容
解密时:使用逆S盒,将已加密数据为逆S盒索引将已加密数据替换为逆S盒子的内容
其实就是将数据按表替换,
例如待加密数据unsigned char data = 9;
加密数据:encryptData = SBox[data] = SBox[9] = 0x01;//注意索引从0开始
解密数据:decryptData = InvSBox[encryptData] = InvSBox[0x01] = 9;
SBox和InvSBox的关系是 data = InvSBox[SBox[data]];还跟GF(2^8) 多项式有关
*/
// 加密用的S盒
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, 0x