当前位置:网站首页>C language AES encryption and decryption
C language AES encryption and decryption
2022-07-03 11:23:00 【Genven_ Liang】
C Language AES encryption
One 、 sketch
remember --C The realization of language AES encryption .
The sample code is packaged : Outside the chain :https://wwm.lanzouq.com/b0camwuah password :7ios
Two 、AES sketch
name | Content | remarks |
---|---|---|
AES describe | AES It belongs to symmetric encryption , Just use a key K Put the data Data1 Encrypted to get Data2, Decryption requires a key K Yes Data2 Decryption reverts to Data1. | Symmetric encryption algorithm means that encryption and decryption use the same key . |
Key length | AES128 yes 16 byte , That is to say 128bit; AES192 yes 24 byte , That is to say 192bit; AES256 yes 32 byte , That is to say 256bit; | |
Number of encryption rounds | AES128 yes 10 round ; AES192 yes 12 round ; AES256 yes 14 round ; | According to the given initial key, multiple keys are expanded . The safety of more rounds is relatively higher . |
Clear text grouping | Plaintext is the data to be encrypted , Press 16 The bytes are encrypted separately as a group , Not enough 16 Bytes can be filled with data . If the filling method is selected , After decryption, the filled data needs to be eliminated . fill style : NoPadding: No fill , Then the encryption length can only be 16 Multiple data , Generally not used PKCS5(PKCS7): A lot of applications , The last group is filled with a few bytes missing | PKCS7 Example : The data to be encrypted is 0123456789abc common 13 Data , Refill 3 One is enough 16 individual ,PKCS7 When filling, it will be filled behind 3 individual 3. |
encryption | Codebook mode (Electronic Codebook Book (ECB)): Press clear text 16 Byte grouping , Each plaintext uses the same initial block vector , Each group was spliced after encryption . Password group link mode (Cipher Block Chaining (CBC)): because ECB Each plaintext uses the same initialization vector , So the same plaintext group in plaintext , The encrypted ciphertext is the same ; To solve this problem, there is CBC Pattern , Each segment of plaintext performs XOR operation with the initial block vector or the ciphertext segment of the previous segment , And then encrypt it with the key ; Simply put, the initial block vector of each plaintext segment is different , In this way, the same plaintext group in plaintext , The encrypted ciphertext is also different . | More practical applications are ECB and CBC. |
3、 ... and 、 Sample code
main.c
#include "aes.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h> //isprint
/* Compile instructions
D:\R\Qt5.7\Tools\mingw530_32\bin\gcc.exe -fdiagnostics-color=always -g D:\VSCode\AES\main.c D:\VSCode\AES\aes.c -o D:\VSCode\AES\main.exe
*/
void PrintData(const char *head, unsigned char *data, unsigned int len)
{
unsigned int i;
printf("%s, len:%u:\r\n", head, len);
// Press 16 I print it out
printf("HEX:[");
for (i=0; i<len; i++) {
printf("%02X ", data[i]);
}
printf("]\r\n");
// Press ASCII Print it out
printf("ASCII:[");
for (i=0; i<len; i++) {
if (isprint(data[i])) {// Printable characters
printf("'%c' ", data[i]);
} else {
printf("\\%02X ", data[i]);
}
}
printf("]\r\n");
}
int main(int argc, char *argv[])
{
unsigned int len;
// Secret key , Define yourself according to the actual situation ,AES128 use 16 byte 、AES192 use 24 byte 、AES256 use 32 byte
unsigned char key[32] = {
0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x41,0x42,0x43,0x44,0x45,0x46,
0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x41,0x42,0x43,0x44,0x45,0x46
};
// Initialization vector , Fixed length 16 individual , When mode=AES_MODE_CBC When used
unsigned char IV[4*Nb] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x41,0x42,0x43,0x44,0x45,0x46};
// Content to encrypt
unsigned char sourceMsg[] = "Hello AES 128/192/256";
// Encrypted content
unsigned char encryptMsg[sizeof(sourceMsg)+16] = {0};
// Decrypted content
unsigned char decryptMsg[sizeof(sourceMsg)+16] = {0};
// Set encryption mode 、 The key
AESInfo_t aesInfo = {
.type = AES256,
.mode = AES_MODE_CBC,
.key = key,
.pIV = IV
};
printf("Build %s %s\r\n", __DATE__, __TIME__);
PrintData("sourceMsg", sourceMsg, strlen((const char *)sourceMsg));
// initialization
AESInit(&aesInfo);
// encryption
len = AESEncrypt(&aesInfo, sourceMsg, encryptMsg, strlen((const char *)sourceMsg));
PrintData("encryptMsg", encryptMsg, len);
// Decrypt
len = AESDecrypt(&aesInfo, decryptMsg, encryptMsg, len);
PrintData("decryptMsg", decryptMsg, len);
return 0;
}
aes.c
#include "aes.h"
#include <string.h>
// GF(2^8) polynomial
#define BPOLY 0x1B //x^4 + x^3 + x^1 + x^0= From the right ,bit0、bit1、bit3、bit4、 by 1,bit2、bit5、bit6、bit7 by 0, namely 00011011=0x1B
/*
SubstituteBytes()
When encrypting : Use S box , Set the data to be encrypted as S The box index replaces the encrypted data with S Contents of the box
When decrypting : Use inverse S box , Invert encrypted data S Box index replaces encrypted data with inverse S The contents of the box
In fact, it is to replace the data according to the table ,
For example, data to be encrypted unsigned char data = 9;
Encrypt data :encryptData = SBox[data] = SBox[9] = 0x01;// Pay attention to the index from 0 Start
Decrypt data :decryptData = InvSBox[encryptData] = InvSBox[0x01] = 9;
SBox and InvSBox The relationship is data = InvSBox[SBox[data]]; Also follow GF(2^8) Polynomial related
*/
// Encryption with S box
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
};
// For decryption SBox
static const unsigned char InvSBox[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
};
/*****************************************************************************
* Function name : RShiftWord
* Function description : To a pWord 4 Rotate byte data to the right .
* Input parameters : pWord -- To move right 4 Bytes of data .
* Output parameters : pWord -- After moving right 4 Bytes of data .
* Return value : nothing .
*****************************************************************************/
static void RShiftWord(unsigned char *pWord)
{
unsigned char temp = pWord[0];
pWord[0] = pWord[1];
pWord[1] = pWord[2];
pWord[2] = pWord[3];
pWord[3] = temp;
}
/*****************************************************************************
* Function name : XorBytes
* Function description : Exclusive or two sets of data .
* Input parameters : pData1 -- The first set of data to XOR .
* pData2 -- The second set of data to XOR .
* nCount -- The length of data participating in XOR .
* Output parameters : pData1 -- The result of XOR .
* Return value : nothing .
*****************************************************************************/
static void XorBytes(unsigned char *pData1, const unsigned char *pData2, unsigned char nCount)
{
unsigned char i;
for (i = 0; i < nCount; i++) {
pData1[i] ^= pData2[i];
}
}
/*****************************************************************************
* Function name : AddKey
* Function description : hold pData data add ( Exclusive or )pKey secret key , The data length is 16 byte .
* Input parameters : pData -- data .
* pKey -- secret key .
* Output parameters : pStpDataate -- Add the data after the sub key .
* Return value : nothing .
*****************************************************************************/
static void AddKey(unsigned char *pData, const unsigned char *pKey)
{
XorBytes(pData, pKey, 4 * Nb);
}
/*****************************************************************************
* Function name : SubstituteBytes
* Function description : adopt S Box replacement data .
* Input parameters : pData -- data .
* dataCnt -- Data length .
* pBox -- Replacement box , Use when encrypting SBox, Use... When decrypting InvSBox
* Output parameters : pData -- Status data after replacement .
* Return value : nothing .
*****************************************************************************/
static void SubstituteBytes(unsigned char *pData, unsigned char dataCnt, const unsigned char *pBox)
{
unsigned char i;
for (i = 0; i < dataCnt; i++) {
pData[i] = pBox[pData[i]];
}
}
/*****************************************************************************
* Function name : ShiftRows
* Function description : Move the status data to .
* Input parameters : pState -- Status data .
* bInvert -- Whether to move backward ( Use... When decrypting ).
* Output parameters : pState -- Status data after migration .
* Return value : nothing .
*****************************************************************************/
static void ShiftRows(unsigned char *pState, unsigned char bInvert)
{
// Be careful : Status data is stored in columns !
unsigned char r; // row, That's ok
unsigned char c; // column, Column
unsigned char temp;
unsigned char rowData[4];
for (r = 1; r < 4; r++) {
// Back up a row of data
for (c = 0; c < 4; c++) {
rowData[c] = pState[r + 4*c];
}
temp = bInvert ? (4 - r) : r;
for (c = 0; c < 4; c++) {
pState[r + 4*c] = rowData[(c + temp) % 4];
}
}
}
/*****************************************************************************
* Function name : GfMultBy02
* Function description : stay GF(28) Domain ride 2 operation .
* Input parameters : num -- The multiplier .
* Output parameters : nothing .
* Return value : num multiply 2 Result .
*****************************************************************************/
static unsigned char GfMultBy02(unsigned char num)
{
if (0 == (num & 0x80)) {
num = num << 1;
} else {
num = (num << 1) ^ BPOLY;
}
return num;
}
/*****************************************************************************
* Function name : MixColumns
* Function description : Mix Columns of data .
* Input parameters : pData -- data .
* bInvert -- Whether to reverse mix ( Use... When decrypting ).
* Output parameters : pData -- Status data after mixing columns .
* Return value : nothing .
*****************************************************************************/
static void MixColumns(unsigned char *pData, unsigned char bInvert)
{
unsigned char i;
unsigned char temp;
unsigned char a0Pa2_M4; // 4(a0 + a2)
unsigned char a1Pa3_M4; // 4(a1 + a3)
unsigned char result[4];
for (i = 0; i < 4; i++, pData += 4) {
temp = pData[0] ^ pData[1] ^ pData[2] ^ pData[3];
result[0] = temp ^ pData[0] ^ GfMultBy02((unsigned char)(pData[0] ^ pData[1]));
result[1] = temp ^ pData[1] ^ GfMultBy02((unsigned char)(pData[1] ^ pData[2]));
result[2] = temp ^ pData[2] ^ GfMultBy02((unsigned char)(pData[2] ^ pData[3]));
result[3] = temp ^ pData[3] ^ GfMultBy02((unsigned char)(pData[3] ^ pData[0]));
if (bInvert) {
a0Pa2_M4 = GfMultBy02(GfMultBy02((unsigned char)(pData[0] ^ pData[2])));
a1Pa3_M4 = GfMultBy02(GfMultBy02((unsigned char)(pData[1] ^ pData[3])));
temp = GfMultBy02((unsigned char)(a0Pa2_M4 ^ a1Pa3_M4));
result[0] ^= temp ^ a0Pa2_M4;
result[1] ^= temp ^ a1Pa3_M4;
result[2] ^= temp ^ a0Pa2_M4;
result[3] ^= temp ^ a1Pa3_M4;
}
memcpy(pData, result, 4);
}
}
/*****************************************************************************
* Function name : BlockEncrypt
* Function description : Encrypt a single block of data .
* Input parameters : pData -- Block data to be encrypted .
* Output parameters : pData -- Encrypted block data .
* Return value : nothing .
*****************************************************************************/
static void BlockEncrypt(AESInfo_t *aesInfoP, unsigned char *pData)
{
unsigned char i;
AddKey(pData, aesInfoP->expandKey);
for (i = 1; i <= aesInfoP->Nr; i++) {
SubstituteBytes(pData, 4 * Nb, SBox);
ShiftRows(pData, 0);
if (i != aesInfoP->Nr) {
MixColumns(pData, 0);
}
AddKey(pData, &aesInfoP->expandKey[4*Nb*i]);
}
}
/*****************************************************************************
* Function name : BlockDecrypt
* Function description : Decrypt a single block of data .
* Input parameters : pData -- Data to decrypt .
* Output parameters : pData -- Decrypted data .
* Return value : nothing .
*****************************************************************************/
static void BlockDecrypt(AESInfo_t *aesInfoP, unsigned char *pData)
{
unsigned char i;
AddKey(pData, &aesInfoP->expandKey[4*Nb*aesInfoP->Nr]);
for (i = aesInfoP->Nr; i > 0; i--) {
ShiftRows(pData, 1);
SubstituteBytes(pData, 4 * Nb, InvSBox);
AddKey(pData, &aesInfoP->expandKey[4*Nb*(i-1)]);
if (1 != i) {
MixColumns(pData, 1);
}
}
}
/*****************************************************************************
* Function name : AESAddPKCS7Padding
* describe : PKCS7 Fill the data in the way
* Input parameters : data -- At most... Are reserved in the back 16 A byte space is used to store the filling value
* len -- Length of data
* Output parameters : data -- Data after adding filler code
* Return value : The length after filling
*****************************************************************************/
static unsigned int AESAddPKCS7Padding(unsigned char *data, unsigned int len)
{
unsigned int newLen;
newLen = len + 16 - (len % 16);
memset(&data[len], newLen-len, newLen-len);
return newLen;
}
/*****************************************************************************
* Function name : AESDelPKCS7Padding
* describe : PKCS7Padding The filled ciphertext is decrypted and the filled value is eliminated
* Input parameters : pData -- Decrypted data
* len -- Length of data
* Output parameters : pData -- Delete the data after the filler code
* Return value : Actual effective data length after deletion , by 0 Indicates that the incoming data is abnormal
*****************************************************************************/
static unsigned int AESDelPKCS7Padding(unsigned char *pData, unsigned int len)
{
if (0 != (len & 0x0F)) {//1 Group 16 byte ,(0 != (len & 0x0F) The explanation is not 16 Multiple
return 0;
}
if (pData[len - 1] > len) {
return 0;
}
return len - pData[len - 1];
}
/*****************************************************************************
* Function name : AESInit
* Function description : initialization
* Input parameters : aesInfoP -- User needs to fill
* Output parameters : nothing .
* Return value : nothing .
*****************************************************************************/
void AESInit(AESInfo_t *aesInfoP)
{
unsigned char i;
unsigned char *pExpandKey;// Extended key
unsigned char Rcon[4] = {0x01, 0x00, 0x00, 0x00};
switch (aesInfoP->type) {
case AES128:
aesInfoP->Nr = 10;
aesInfoP->Nk = 16;
break;
case AES192:
aesInfoP->Nr = 12;
aesInfoP->Nk = 24;
break;
case AES256:
aesInfoP->Nr = 14;
aesInfoP->Nk = 32;
break;
default:
aesInfoP->Nr = 10;
aesInfoP->Nk = 16;
break;
}
// Expand the key
memcpy(aesInfoP->expandKey, aesInfoP->key, 4 * aesInfoP->Nk);// The first is the original key ,
pExpandKey = &aesInfoP->expandKey[4*aesInfoP->Nk]; // Expand the key AES128:10 individual 、AES192:12 individual 、AES256:14 individual
for (i = aesInfoP->Nk; i < Nb*(aesInfoP->Nr + 1); pExpandKey += 4, i++) {
memcpy(pExpandKey, pExpandKey - 4, 4);
if (0 == i % aesInfoP->Nk) {
RShiftWord(pExpandKey);
SubstituteBytes(pExpandKey, 4, SBox);
XorBytes(pExpandKey, Rcon, 4);
Rcon[0] = GfMultBy02(Rcon[0]);
} else if (6 < aesInfoP->Nk && i % aesInfoP->Nk == Nb) {
SubstituteBytes(pExpandKey, 4, SBox);
}
XorBytes(pExpandKey, pExpandKey - 4 * aesInfoP->Nk, 4);
}
}
/*****************************************************************************
* Function name : AESEncrypt
* Function description : Encrypt data
* Input parameters : aesInfoP -- contain key、 Initialization information such as encryption method
* pPlainText -- Data to encrypt , The length of nDataLen byte .
* dataLen -- Data length , In bytes , It needs to be an integral multiple ,AES128:16 Multiple 、AES192:24 Multiple 、AES256:32 Multiple .
* Output parameters : pCipherText -- Encrypted data , Reserved length :dataLen+16
* Return value : Length of decrypted data .
*****************************************************************************/
unsigned int AESEncrypt(AESInfo_t *aesInfoP, const unsigned char *pPlainText, unsigned char *pCipherText,
unsigned int dataLen)
{
unsigned int i;
const void *pIV;
if (pPlainText != pCipherText) {
memcpy(pCipherText, pPlainText, dataLen);
}
// Must be 16 Integer multiple , Not enough filling ,pkcs7 The algorithm is missing n repair n individual n, such as 13 Byte data is missing 3 individual , I'll make it up later 3 individual 3; If it happens to be 16 Multiple , Just fill 16 individual 16
dataLen = AESAddPKCS7Padding(pCipherText, dataLen);
pIV = aesInfoP->pIV;
for (i = dataLen / (4 * Nb); i > 0 ; i--, pCipherText += 4 * Nb) {
if (AES_MODE_CBC == aesInfoP->mode) {
XorBytes(pCipherText, pIV, 4 * Nb);
}
BlockEncrypt(aesInfoP, pCipherText);
pIV = pCipherText;
}
return dataLen;
}
/*****************************************************************************
* Function name : AESDecrypt
* Function description : Decrypt data
* Input parameters : aesInfoP -- contain key、 Initialization information such as encryption method
* pPlainText -- Data to encrypt , The length of dataLen byte .
* dataLen -- Data length , In bytes , It needs to be an integral multiple ,AES128:16 Multiple 、AES192:24 Multiple 、AES256:32 Multiple .
* Output parameters : pCipherText -- Encrypted data , It can be done with pCipherText identical
* Return value : Return the decrypted data length .
*****************************************************************************/
unsigned int AESDecrypt(AESInfo_t *aesInfoP, unsigned char *pPlainText, const unsigned char *pCipherText,
unsigned int dataLen)
{
unsigned int i;
unsigned char *pPlainTextBack = pPlainText;
if (pPlainText != pCipherText) {
memcpy(pPlainText, pCipherText, dataLen);
}
// When mode=AES_MODE_CBC You need to decrypt the last piece of data
pPlainText += dataLen - 4 * Nb;
for (i = dataLen / (4 * Nb); i > 0 ; i--, pPlainText -= 4 * Nb) {
BlockDecrypt(aesInfoP, pPlainText);
if (AES_MODE_CBC == aesInfoP->mode) {
if (1 == i) {// The original first piece of data is encrypted with initial variables
XorBytes(pPlainText, aesInfoP->pIV, 4 * Nb);
} else {
XorBytes(pPlainText, pPlainText - 4 * Nb, 4 * Nb);
}
}
}
// Because the data needs 16 Byte alignment , There may be filled data , You need to remove the following fill data
return AESDelPKCS7Padding(pPlainTextBack, dataLen);
}
aes.h
#ifndef _AES_H
#define _AES_H
#define Nb 4 // Encryption and decryption data block size , Fixed for 4
// The key length corresponding to the encryption type , Company bit
typedef enum {
AES128 = 128,
AES192 = 192,
AES256 = 256,
} AESType_t;
// Encryption and decryption mode
typedef enum {
AES_MODE_ECB = 0, // Electronic codebook mode
AES_MODE_CBC = 1, // Password group link mode
} AESMode_t;
typedef struct {
int Nk; // Users do not need to fill , Key length , Unit byte , AES128:Nk=16、AES192:Nk=24、AES256:Nr=32
int Nr; // Users do not need to fill , The number of rounds of encryption AES128:Nr=10、AES192:Nr=12、AES256:Nr=14
int type;// Users need to fill , relation AESType_t
int mode;// Users need to fill , relation AESMode_t
const void *key;// Users need to fill , The key
const void *pIV;// Users need to fill , Initialization vector , When mode=AES_MODE_CBC You need to set , Point to unsigned char IV[4*Nb];
//AES Expand the key , The size AES128:4*Nb*(10+1):4*Nb*(12+1)、AES256:4*Nb*(14+1)
unsigned char expandKey[4*Nb*(14+1)];// Users do not need to fill ,[4*Nb*(Nr+1)]、 Here press the largest AES256 To initialize
} AESInfo_t;
/*****************************************************************************
* Function name : AESInit
* Function description : initialization
* Input parameters : aesInfoP -- User needs to fill
* Output parameters : nothing .
* Return value : nothing .
*****************************************************************************/
extern void AESInit(AESInfo_t *aesInfoP);
/*****************************************************************************
* Function name : AESEncrypt
* Function description : Encrypt data
* Input parameters : aesInfoP -- contain key、 Initialization information such as encryption method
* pPlainText -- Data to encrypt , The length of nDataLen byte .
* dataLen -- Data length , In bytes , It needs to be an integral multiple ,AES128:16 Multiple 、AES192:24 Multiple 、AES256:32 Multiple .
* Output parameters : pCipherText -- Ciphertext , That is, the data encrypted by plaintext , It can be done with pPlainText identical .
* Return value : Length of decrypted data ..
*****************************************************************************/
extern unsigned int AESEncrypt(AESInfo_t *aesInfoP, const unsigned char *pPlainText, unsigned char *pCipherText, unsigned int dataLen);
/*****************************************************************************
* Function name : AESDecrypt
* describe : Decrypt data
* Input parameters : aesInfoP -- contain key、 Initialization information such as encryption method
* pPlainText -- Data to encrypt , The length of nDataLen byte .
* dataLen -- Data length , In bytes , It needs to be an integral multiple ,AES128:16 Multiple 、AES192:24 Multiple 、AES256:32 Multiple .
* Output parameters : pCipherText -- Encrypted data , It can be done with pCipherText identical
* Return value : Return the decrypted data length .
*****************************************************************************/
extern unsigned int AESDecrypt(AESInfo_t *aesInfoP, unsigned char *pPlainText, const unsigned char *pCipherText, unsigned int nDataLen);
#endif /* _AES_H */
test result :
linux In the environment
Windows In the environment :
Reference from :https://blog.csdn.net/chengjunchengjun/article/details/109322987
边栏推荐
- Intel 13th generation core flagship exposure, single core 5.5ghz
- 如何让让别人畏惧你
- Error installing the specified version of pilot
- 多维度监控:智能监控的数据基础
- AMS Series 1 - AMS startup process
- Internet socket (non) blocking write/read n bytes
- Function details of CorelDRAW graphics suite 2022
- 高精度室内定位技术,在智慧工厂安全管理的应用
- 表空间创建管理及控制文件管理
- 【Proteus仿真】74HC154 四线转12线译码器组成的16路流水灯
猜你喜欢
A simple method of adding dividing lines in recyclerview
php服务器 与redis交互大量CLOSE_WAIT分析
高精度室内定位技术,在智慧工厂安全管理的应用
Leetcode 46: full arrangement
11. Provider service registration of Nacos service registration source code analysis
Activity and fragment lifecycle
如何清理v$rman_backup_job_details视图 报错ORA-02030
2021 reading summary (continuously updating)
Processes and threads
The element form shows the relationship between elementary transformation and elementary matrix
随机推荐
Crawl with requests
CSRF
Linear table sequence table comprehensive application problem p18
VPP三层网络互联配置
Solutions of n-ary linear equations and their criteria
如何成为一名高级数字 IC 设计工程师(1-2)Verilog 编码语法篇:Verilog 1995、2001、2005 标准
ConstraintLayout跟RelativeLayout嵌套出现的莫名奇妙的问题
One hot code
Lecture 1 number field
2021 postgraduate entrance examination mathematics 2 linear algebra
用了这么久线程池,你真的知道如何合理配置线程数吗?
Unity移动端游戏性能优化简谱之 画面表现与GPU压力的权衡
How to: configure ClickOnce trust prompt behavior
使用onvif协议操作设备
Definition and properties of summation symbols
Illustrated network: what is virtual router redundancy protocol VRRP?
线性表顺序表综合应用题P18
2021 reading summary (continuously updating)
Inexplicable problems in the nesting of constraintlayout and relativelayout
ASP.NET-酒店管理系統