前面写了ECB模式加密:ECB加密
很好奇CBC模式加密是如何实现的。
CBC模式的工作原理:
1.初始化向量:CBC模式需要有一个初始化向量IV,它的大小与块大小相同。IV通常是随机生成。它与第一个明文块一起使用,确保相同的明文在不同的加密过程中生成不同的密文。
2.加密:第一个明文块与IV异或,结果通过加密算法加密(比如AES),生成第一个密文块。接下来第一个密文块再与第二个明文块进行异或,结果再进行加密生成第二个密文块。不断重复,直到结束。
3.解密:第一个密文块通过解密算法,得到一个中间结果。将中间结果与IV进行异或运算,恢复第一个明文块。接着对第二个密文块进行解密,并于第一个密文块进行异或,恢复第二个明文块,不断重复,直到完全解密。
通过以上过程发现,CBC相较于ECB安全性增强,每个密文块,不仅依赖于自身,还依赖于前一个密文块。缺点也是显而易见的,就是无法并行加密,加密过程和解密过程是按顺序进行的。
C++实现方式:
#include <openssl/evp.h>//支持各种加密算法的接口
#include <openssl/rand.h>//用它生成密钥和IV
#include <cstring>
#include <iostream>
const int AES_KEY_LENGTH = 256; // 密钥长度256比特
const int AES_BLOCK_SIZE = 16; // AES 每个块16比特
void handleErrors() {
std::cerr << "发生错误!\n";
exit(1);
}//如果发生错误,调用该函数提示
// AES CBC模式加密
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();//进行加密
if (!ctx) handleErrors();//加密失败给出错误提示
if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)//首次加密,使用初始化向量IV
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 CBC模式解密
int decrypt(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_cbc(), NULL, key, iv) != 1)
handleErrors();//首次解密,使用iv
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];
// 随机生成密钥和IV
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(plaintext, strlen((char *)plaintext), key, iv, ciphertext);
// 解密
int decryptedtext_len = decrypt(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;
}
最后的运行结果: