OpenSSL AES错误加密



我在下面有一些代码。我的问题是我有一个加密和解密字符数组的奇怪结局。

#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 之类的东西或迭代字符以打印数组。

ciphertextplaintext 不是 C 样式的字符串。它们只是指向一系列unsigned char的指针。printf 中的%s说明符需要一个以 null 结尾的字符串才能打印。您有两种选择:

  • 确保 ciphertextplaintext 都以 null 结尾
  • 遍历数组(因为您知道它们的长度(并单独打印每个字符

通常,密码学中的所有此类字节字符串都使用十六进制,因此,使用后者可能会更好。

大多数加密算法会在加密之前填充数据,以确保无法从加密消息的确切长度推断出信息。一些工具甚至在加密数据之前添加压缩(然后填充(。

因此,一长串统一字符可能是填充的。

其余可能意味着您看到一些未初始化的数据。这意味着您提供的缓冲区在实际消息后不会用零填充,因此您可能会在此过程中加密垃圾。或者,在解密时,您不会在解密的数据停止时将预期的字符串归零终止。

最新更新