使用OpenSSL AES加解密:含0值字节数组的加密问题
如何正确使用OpenSSL EVP接口加密含0值的字节数据?
我按照OpenSSL官方Wiki的EVP对称加解密示例代码实现功能,同时参考了Stack Overflow上的相关建议。用字符串作为输入时一切正常,但换成包含0值的字节数组作为明文时,加密解密结果都不对——看起来是数据里的0被当成了字符串的空终止符,导致只处理了第一个0之前的字节。
字符串输入时的正常输出
Plaintext buffer is: 0000 - 48 65 6c 6c 6f 20 66 72-6f 6d 20 42 69 72 6d 69 Hello from Birmi Ciphertext is: 0000 - 97 24 23 31 cd 36 47 75-c9 e9 56 a8 44 9a e4 9c .$#1.6Gu..V.D... 0010 - 93 6e 0b 35 e2 03 .n.5.. Decrypted text is: Hello from Birmingham! 0000 - 48 65 6c 6c 6f 20 66 72-6f 6d 20 42 69 72 6d 69 Hello from Birmi 0010 - 6e 67 68 61 6d 21 ngham!
字节数组输入时的异常输出
Converted raw bytes to ☺Plaintext buffer is: 0000 - 01 00 01 02 00 00 00 00-00 00 00 00 00 00 00 00 ................ Ciphertext is: 0000 - de . Decrypted text is: ☺ 0000 - 01 .
复现步骤
- 取OpenSSL Wiki上的EVP对称加解密示例代码
- 将原明文定义:
/* Message to be encrypted */ unsigned char *plaintext = (unsigned char *)"The quick brown fox jumps over the lazy dog";
替换为:
unsigned char bytearray[16] = {1,0,1,2}; unsigned char* plaintext = &bytearray[0];
解决方法
核心问题是混淆了字符串和字节数组的长度传递方式——字符串可以用strlen()获取长度,但字节数组(含0值)必须显式传递实际长度,不能依赖空终止符。
具体修改点:
- 传递明确的明文长度:
不要用strlen((char*)plaintext)来计算长度,而是直接指定字节数组的实际有效长度(比如示例中的16,或者你实际使用的长度)。示例代码:// 替换原strlen调用,明确指定长度 size_t plaintext_len = 16; // 对应bytearray的总大小 - 确保EVP接口调用使用正确长度:
在调用EVP_EncryptUpdate和EVP_DecryptUpdate时,传入显式指定的长度,而非字符串截断后的长度。示例修改:int len; // 加密时传入plaintext_len,而非strlen结果 EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len); ciphertext_len = len; EVP_EncryptFinal_ex(ctx, ciphertext + len, &len); ciphertext_len += len; - 正确处理解密输出:
解密结果可能包含0值,不能用strlen或字符串打印方法判断结束,必须通过EVP_DecryptUpdate和EVP_DecryptFinal_ex返回的长度值,拼接出完整的解密数据。
内容的提问来源于Stack Exchange,提问作者MikeF
相关产品推荐
相关产品推荐

