我在下面有一些代码。我的问题是我有一个加密和解密字符数组的奇怪结局。
#include <iostream>
#include <opensslevp.h>
#define AES_BLOCK_SIZE 16
static EVP_CIPHER_CTX Encrypt_Context, Decrypt_Context;
int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx,
EVP_CIPHER_CTX *d_ctx)
{
int i, nrounds = 1;
unsigned char key[16], iv[16];
i = EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv);
if (i != 16) {
printf("Key size is %d bits - should be 128 bitsn", i);
return -1;
}
EVP_CIPHER_CTX_init(e_ctx);
EVP_EncryptInit_ex(e_ctx, EVP_aes_128_cbc(), NULL, key, iv);
EVP_CIPHER_CTX_init(d_ctx);
EVP_DecryptInit_ex(d_ctx, EVP_aes_128_cbc(), NULL, key, iv);
return 0;
}
unsigned char *aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len)
{
int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
unsigned char *ciphertext = (unsigned char *)malloc(c_len);
EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL);
EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len);
EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len);
*len = c_len + f_len;
return ciphertext;
}
unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
{
int p_len = *len, f_len = 0;
unsigned char *plaintext = (unsigned char*)malloc(p_len);
EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len);
*len = p_len + f_len;
return plaintext;
}
void main()
{
unsigned char * data_to_encrypt = (unsigned char*)"aaaaaaaaabbbbbbbbbbbbbbccccccccc";
unsigned char *key_data = (unsigned char *)"aaaaaaaaaaaaaaaa";
int key_data_len = strlen((const char*) key_data);
char * ciphertext;
char * plaintext;
aes_init(key_data, 16, NULL, &Encrypt_Context, &Decrypt_Context);
int length = strlen((const char*) data_to_encrypt)-1;
printf("Clear text :%sn", data_to_encrypt);
ciphertext = (char *)aes_encrypt(&Encrypt_Context, data_to_encrypt, &length);
printf("Crypted text :%sn", ciphertext);
plaintext = (char *)aes_decrypt(&Decrypt_Context, (unsigned char*)ciphertext, &length);
printf("Decrypted text :%sn", plaintext);
}
有了这段代码,我进入了控制台:
加密文本末尾的══════════════¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤明文:啊 加密文本:°ЁТ☼ #єз▬├^^,♦Ёфм:ЇъШ╙y╒КzukЩ u@8¤════════════════¤¤¤¤¤¤¤═══¤¤¤═══¤¤¤═══¤¤═══¤¤═══¤¤¤¤═══¤¤¤¤═══¤¤¤¤¤═══¤¤¤¤¤═══¤¤¤ 解密文字:aaaabbbbbbbcc☺
¤¤¤¤¤¤¤¤
¤¤� ☺我的代码有什么问题?
谢谢!
加密例程处理二进制数据,而不是 C 字符串,它们返回指针的数组不以 null 结尾,因此当使用 printf
(它需要以 null 结尾的字符串(打印时,你会得到随机垃圾,恰好位于这些数组之后。
要解决此问题,请确保 null 终止,使用 fwrite
之类的东西或迭代字符以打印数组。
ciphertext
和 plaintext
不是 C 样式的字符串。它们只是指向一系列unsigned char
的指针。printf
中的%s
说明符需要一个以 null 结尾的字符串才能打印。您有两种选择:
- 确保
ciphertext
和plaintext
都以 null 结尾 - 遍历数组(因为您知道它们的长度(并单独打印每个字符
通常,密码学中的所有此类字节字符串都使用十六进制,因此,使用后者可能会更好。
大多数加密算法会在加密之前填充数据,以确保无法从加密消息的确切长度推断出信息。一些工具甚至在加密数据之前添加压缩(然后填充(。
因此,一长串统一字符可能是填充的。
其余可能意味着您看到一些未初始化的数据。这意味着您提供的缓冲区在实际消息后不会用零填充,因此您可能会在此过程中加密垃圾。或者,在解密时,您不会在解密的数据停止时将预期的字符串归零终止。