2012-05-18 85 views
0

我在下面有一些代码。我的问题是,我有一个奇怪的结束加密和解密字符数组。OpenSSL AES加密错误

#include <iostream> 
#include <openssl\evp.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 bits\n", 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 :%s\n", data_to_encrypt); 

    ciphertext = (char *)aes_encrypt(&Encrypt_Context, data_to_encrypt, &length); 
    printf("Crypted text :%s\n", ciphertext); 

    plaintext = (char *)aes_decrypt(&Decrypt_Context, (unsigned char*)ciphertext, &length); 
    printf("Decrypted text :%s\n", plaintext); 
} 

有了这个代码,我越来越控制台:

清除文字:aaaaaaaaabbbbbbbbbbbbbbccccccccc 加密后的文本:°ЁТ☼#єз▬├^^,♦Ёфм:ЇъШ╙y╒КzukЩ[email protected]¤ ═══════════════¤¤¤¤ 解密正文:aaaaaaaaabbbbbbbbbbbbbbcccccccc☺¤¤¤¤

什么是═════════════在加密的文本和结尾处¤¤¤¤到底解密?我的代码有什么问题?

谢谢!

+0

这可能是填充:) – 0xC0000022L

回答

2

加密程序处理二进制数据,而不是C字符串,它们返回指针的数组不是以NULL结尾的,所以当使用printf(它期望以null结尾的字符串)打印时,垃圾恰好位于这些数组之后。

要解决这个问题,请确保空终止,使用类似fwrite或迭代字符以打印数组。

+0

所以我的代码工作正常?这只是printf的问题? – Roman

+0

@罗曼:是的,就是这样。 – Fanael

2

ciphertextplaintext不是C风格的字符串。它们仅仅是指向一组unsigned char s的指针。 printf中的%s说明符需要以null结尾的字符串才能打印。你有两个选择:

  • 确保两个ciphertextplaintext是空值终止
  • 循环阵列上(因为你知道它们的长度),并打印出每个字符分别

通常情况下,所有的密码学中的这种字节串使用十六进制,所以,用后者可能会更好。

0

大多数加密算法会在加密前填充数据,以确保无法从加密消息的确切长度中推导出信息。有些工具甚至在加密数据之前添加压缩(接着是填充)。

所以统一字符的长字符串可能是填充。

其余可能意味着你看到一些未初始化的数据。这意味着您给出的缓冲区在实际消息之后没有填满零,因此您可能正在加密垃圾。或者,解密时,在解密数据停止的位置,您不会零终止您期望的字符串。