AES加密基本原理:
1.把明文按照128bit拆分成若干個明文塊。
2.按照選擇的填充方式來填充最後一個明文塊。
3.每一個明文塊利用AES加密器和密鑰,加密成密文塊。
4.拼接所有的密文塊,成爲最終的密文結果。
AES支持三種長度的密鑰:
128位,192位,256位
填充方式:
NoPadding:
不做任何填充,但是要求明文必須是16字節的整數倍。
PKCS5Padding(默認):
如果明文塊少於16個字節(128bit),在明文塊末尾補足相應數量的字符,且每個字節的值等於缺少的字符數。
AES工作模式:
AES的工作模式,體現在把明文塊加密成密文塊的處理過程中。AES加密算法提供了五種不同的工作模式:
CBC、ECB、CTR、CFB、OFB
Linux C實現aes128_cbc_pkcs5pading:
#include <openssl/ssl.h>
#include <openssl/aes.h>
#define BLOCK_SIZE 16
/* sz_in_buff 輸入字符串
* key 爲密鑰
* iv爲偏移量
* sz_out_buff 加密輸出字符串
*/
int aes_encrypt_pkcs5pading(unsigned char *sz_in_buff, int sz_in_len, unsigned char *key,unsigned char *iv, unsigned char *sz_out_buff)
{
EVP_CIPHER_CTX ctx;
int len=0,isSuccess = 0;
unsigned char in[BLOCK_SIZE];
int outl = 0;
int outl_total = 0;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
while(sz_in_len >=BLOCK_SIZE)
{
memcpy(in, sz_in_buff, BLOCK_SIZE);
sz_in_len -= BLOCK_SIZE;
sz_in_buff += BLOCK_SIZE;
isSuccess = EVP_EncryptUpdate(&ctx, sz_out_buff + outl_total, &outl, in, BLOCK_SIZE);
if(!isSuccess)
{
printf("EVP_EncryptUpdate() failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
outl_total += outl;
}
if(sz_in_len > 0)
{
memcpy(in, sz_in_buff, sz_in_len);
isSuccess = EVP_EncryptUpdate(&ctx,sz_out_buff + outl_total, &outl, in, sz_in_len);
outl_total += outl;
isSuccess = EVP_EncryptFinal_ex(&ctx,sz_out_buff + outl_total,&outl);
if(!isSuccess)
{
printf("EVP_EncryptFinal_ex() failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
outl_total += outl;
}
EVP_CIPHER_CTX_cleanup(&ctx);
return outl_total;
}
/* sz_in_buff 輸入解密字符串
* key 爲密鑰
* iv爲偏移量
* sz_out_buff 輸出解密後字符串
*/
int aes_decrypt_pkcs5pading(unsigned char *sz_in_buff, int sz_in_length, unsigned char *key,unsigned char *iv, unsigned char *sz_out_buff)
{
unsigned char in[BLOCK_SIZE];
int outl = 0;
int outl_total = 0;
int isSuccess;
EVP_CIPHER_CTX ctx;
//初始化ctx,加密算法初始化
EVP_CIPHER_CTX_init(&ctx);
isSuccess = EVP_DecryptInit_ex(&ctx,EVP_aes_128_cbc(),NULL,key,iv);
if(!isSuccess)
{
printf("EVP_DecryptInit_ex() failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
//解密數據
while(sz_in_length >BLOCK_SIZE)
{
memcpy(in, sz_in_buff, BLOCK_SIZE);
sz_in_length -= BLOCK_SIZE;
sz_in_buff += BLOCK_SIZE;
isSuccess = EVP_DecryptUpdate(&ctx, sz_out_buff + outl_total, &outl, in, BLOCK_SIZE);
if(!isSuccess)
{
printf("EVP_DecryptUpdate() failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
outl_total += outl;
}
if(sz_in_length > 0)
{
memcpy(in, sz_in_buff, sz_in_length);
isSuccess = EVP_DecryptUpdate(&ctx, sz_out_buff + outl_total, &outl, in, sz_in_length);
outl_total += outl;
}
/*解密數據塊不爲16整數倍時執行 */
if(sz_in_length % BLOCK_SIZE != 0)
{
isSuccess = EVP_DecryptFinal_ex(&ctx, sz_out_buff + outl_total, &outl);
if(!isSuccess)
{
printf("EVP_DecryptFinal_ex() failed\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
outl_total += outl;
}
EVP_CIPHER_CTX_cleanup(&ctx);
return outl_total;
}