CTR模式克服了CBC需要串行加密的劣势。它不需要依赖块之间的链接,可以并行处理加密操作,不需要填充,适合处理任意长度的数据。
CTR模式的加密步骤:
1.先定义一个初始向量(IV)和计数器(Counter)。
2.对每个块的计数器值进行加密生成伪随机密钥流。
3.将密钥流和明文按位异或运算,生成密文。
4.计数器逐步增加,直到加密完成。
CTR不需要依赖前一个密文块,可以同时处理不同的块,因此它在并行化处理时性能更好。
解密过程
与加密过程相同,使用相同的IV和密钥生成伪随机数流。
将伪随机数流与密文进行异或操作,生成原始的明文块。
C++代码实现如下:
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <cstring>
#include <iostream>
const int AES_KEY_LENGTH = 256;
const int AES_BLOCK_SIZE = 16;
void handleErrors() {
std::cerr << "发生错误\n";
exit(1);
}
// AES CTR模式加密
int encrypt_ctr(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();// *ciphertext直接对密文数据进行更改
if (!ctx) handleErrors();//失败给出错误提示
if (EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv) != 1)
handleErrors();//初始化加密操作
int len;
int ciphertext_len;
if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) != 1)
handleErrors();//执行加密操作
ciphertext_len = len;
if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1)
handleErrors();//完成加密
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
// AES CTR模式解密
int decrypt_ctr(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) handleErrors();
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv) != 1)
handleErrors();//初始化解密过程
int len;
int plaintext_len;
if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1)
handleErrors();//执行解密 操作
plaintext_len = len;
if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1)
handleErrors();
plaintext_len += len;//完成解密
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
int main() {
unsigned char key[AES_KEY_LENGTH / 8];//定义密钥长度
unsigned char iv[AES_BLOCK_SIZE];//初始化向量,通过ssl中的rand生成
if (!RAND_bytes(key, sizeof(key)) || !RAND_bytes(iv, sizeof(iv))) {
std::cerr << "Error generating key/iv\n";
return 1;
}//随机生成密钥与初始化向量
unsigned char plaintext[] = "Hello,world!";
unsigned char ciphertext[128];//密文
unsigned char decryptedtext[128];//解密后的结果
std::cout << "\n明文:\n" << plaintext << std::endl;
int ciphertext_len = encrypt_ctr(plaintext, strlen((char *)plaintext), key, iv, ciphertext);
//计算加密后的密文长度
int decryptedtext_len = decrypt_ctr(ciphertext, ciphertext_len, key, iv, decryptedtext);
decryptedtext[decryptedtext_len] = '\0';
//计算解密后的明文长度
std::cout << "对明文加密后的密文:\n";
for (int i = 0; i < ciphertext_len; i++) {
std::cout << std::hex << (int)ciphertext[i];
}
std::cout << "\n解密后的明文:\n" << decryptedtext << std::endl;
return 0;
}
执行结果如图: