AES演算法是一種對稱加密演算法,全稱為高階加密標準(Advanced Encryption Standard)。它是一種分組密碼,以128
位元為一個分組進行加密,其金鑰長度可以是128
位元、192
位元或256
位元,因此可以提供不同等級的安全性。該演算法採用了替代、置換和混淆等技術,以及多輪加密和金鑰擴充套件等機制,使得其加密效果優秀,安全性高,被廣泛應用於各種領域中,如資料加密、檔案加密、網路安全等。
AES演算法加密和解密使用的金鑰是相同的,該演算法加密和解密速度較快,適用於對大量資料進行加密解密的場景。在實際應用中,通常採用混合加密方式,即使用RSA演算法加密對稱加密演算法中的金鑰,再使用對稱加密演算法加密資料,以保證資料的機密性和加密解密的效率。
AES演算法常用兩種加密模式,即CBC和ECB模式,它們分別具有不同的優缺點。
-
ECB(Electronic Codebook,電子密碼本)模式是最簡單的分組密碼工作模式,將每個明文塊獨立加密,同樣的金鑰加密同樣的明文塊得到的密文也是一樣的,因此容易被攻擊者利用重複的密文進行分析破解。ECB模式加密效率高,適用於短報文加密,但不適用於長報文加密。
-
CBC(Cipher Block Chaining,密碼塊鏈)模式是一種分組密碼工作模式,先將明文分組,然後對每個分組進行加密,加密時使用上一塊密文作為輸入,因此相同的明文塊在不同位置上得到的密文是不同的,可以防止被攻擊者利用重複的密文進行分析破解。CBC模式加密效率較低,但適用於長報文加密,因為不同的明文塊之間互相影響,增加了安全性。
在實際應用中,通常採用CBC
模式進行加密,因為它比ECB
模式更安全,但加密效率較低。此外,還有其他的加密模式,如CFB、OFB、CTR
等,不同的加密模式適用於不同的場景,需要根據實際需求進行選擇。
OpenSSL庫提供了對AES
加密的支援,但在使用時讀者還是需要自行封裝一些通用加解密函式,如下程式碼片段是筆者常用的一些函式總結,其中aes_cbc_encrypt
函式用於使用CBC模式對特定字串加密,aes_cbc_decrypt
則使用CBC模式對字串進行解密,第二個函式AES
函式則是使用OpenSSL
庫預設的加解密函式二次封裝實現的。
#include <iostream>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>
extern "C"
{
#include <openssl/applink.c>
}
#pragma comment(lib,"libssl_static.lib")
#pragma comment(lib,"libcrypto.lib")
// CBC模式加密
int aes_cbc_encrypt(char* in, char* key, char* out)
{
if (!in || !key || !out)
return 0;
unsigned char iv[AES_BLOCK_SIZE];
for (int i = 0; i < AES_BLOCK_SIZE; ++i)
iv[i] = 0;
AES_KEY aes;
if (AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
}
int len = strlen(in);
AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT);
return 1;
}
// CBC模式解密
int aes_cbc_decrypt(char* in, char* key, char* out)
{
if (!in || !key || !out)
return 0;
// 加密的初始化向量
unsigned char iv[AES_BLOCK_SIZE];
// iv一般設定為全0
for (int i = 0; i < AES_BLOCK_SIZE; ++i)
iv[i] = 0;
AES_KEY aes;
if (AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
}
int len = strlen(in);
AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT);
return 1;
}
// 將加密與解密整合在一起
void AES(unsigned char* InBuff, unsigned char* OutBuff, unsigned char* key, char* Type)
{
if (strcmp(Type, "encode") == 0)
{
AES_KEY AESEncryptKey;
AES_set_encrypt_key(key, 256, &AESEncryptKey);
AES_encrypt(InBuff, OutBuff, &AESEncryptKey);
}
else if (strcmp(Type, "decode") == 0)
{
AES_KEY AESDecryptKey;
AES_set_decrypt_key(key, 256, &AESDecryptKey);
AES_decrypt(InBuff, OutBuff, &AESDecryptKey);
}
}
有了上述演算法封裝,接下來筆者將依次演示這幾種不同的加密函式是如何被應用的,首先簡單介紹一下aes_cbc_encrypt
與aes_cbc_decrypt
這兩個函式都是自己封裝的AES加解密演算法,這兩個演算法引數傳遞保持一致,第一個引數都是指定需要加密的緩衝區,第二個引數則是指定加密所使用的key,第三個引數是處理後的結果。
int main(int argc, char* argv[])
{
char szBuffer[1024] = "hello lyshark";
char szDst[1024] = { 0 };
char szSrc[1024] = { 0 };
// 計算一串金鑰
char key[AES_BLOCK_SIZE] = { 0 };
for (int x = 0; x < AES_BLOCK_SIZE; x++)
{
key[x] = 32 + x;
}
// AES加密
if (aes_cbc_encrypt(szBuffer, key, szDst) != 0)
{
std::cout << "加密後長度: " << strlen(szDst) << std::endl;
}
// AES解密
if (aes_cbc_decrypt(szDst, key, szSrc) != 0)
{
std::cout << "解密內容: " << szSrc << std::endl;
}
system("pause");
return 0;
}
上述程式碼片段則是透過AES實現對資料加解密處理的功能,如下是這段程式碼的輸出效果;
第二種呼叫方式是採用API
實現,其中的AES
函式,透過AES_set_encrypt_key
設定加密金鑰,並直接呼叫AES_encrypt
實現資料加密,反之,透過AES_set_decrypt_key
設定解密金鑰,並呼叫AES_decrypt
解密,這段程式碼呼叫方式如下所示;
int main(int argc, char* argv[])
{
unsigned char Buffer[1024] = "hello lyshark";
unsigned char EncodeBuf[1024] = { 0 };
unsigned char DecodeBuf[1024] = { 0 };
unsigned char aes_key[32] = { 0 };
// 隨機生成金鑰
for (int x = 0; x < 32; x++)
{
int ch = rand() % 5;
aes_key[x] = (char)ch;
}
AES(Buffer, EncodeBuf, (unsigned char *)aes_key, (char*)"encode");
std::cout << "加密資料長度: " << strlen((char *)EncodeBuf) << std::endl;
AES(EncodeBuf, DecodeBuf, (unsigned char*)aes_key, (char*)"decode");
std::cout << "解密資料: " << DecodeBuf << std::endl;
system("pause");
return 0;
}
如上程式碼,透過呼叫AES
函式時,傳入encode
實現資料加密,傳入decode
實現資料解密,如下圖所示;