【发布时间】:2021-05-19 04:31:19
【问题描述】:
我正在尝试使用 openssl 在 C 中编写 AES 加密/解密程序。但是,当我尝试解密消息时,我得到了错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:错误的最终块长度。
void aes_encrypt(unsigned char* in, int inl, unsigned char *out, int* len, unsigned char * key){
unsigned char iv[16] = "encryptionIntVec";
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv);
*len = 0;
int outl = 0;
EVP_EncryptUpdate(&ctx, out+*len, &outl, in+*len, inl);
*len+=outl;
int test = inl>>4;
if(inl != test<<4){
EVP_EncryptFinal_ex(&ctx,out+*len,&outl);
*len+=outl;
}
EVP_CIPHER_CTX_cleanup(&ctx);
}
void aes_decrypt(unsigned char* in, int inl, unsigned char *out, unsigned char *key){
unsigned char iv[16] = "encryptionIntVec";
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
int result;
result = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv);
if(result > 0) {
printf("passed\n");
} else {
printf("failed\n");
}
int len = 0;
int outl = 0;
result = EVP_DecryptUpdate(&ctx, out+len, &outl, in+len, inl);
if(result > 0) {
printf("passed\n");
} else {
printf("failed\n");
}
len += outl;
result = EVP_DecryptFinal_ex(&ctx, out+len, &outl);
if(result > 0) {
printf("passed\n");
} else {
printf("failed\n");
ERR_print_errors_fp(stdout);
}
len+=outl;
out[len]=0;
EVP_CIPHER_CTX_cleanup(&ctx);
}
int main()
{
unsigned char content[400];
unsigned char key[] = "0123456789abcdef0123456789abcdef";
/******************Block 1*****************************/
unsigned char en[400],de[400],base64[400], base64_out[400];
int len;
memset(content, 0,400);
memset(en, 0, 400);
memset(de, 0, 400);
memset(base64, 0,400);
memset(base64_out, 0, 400);
strcpy((char *)content, "loc: 123.2132412, -39.123142");
printf("%d %s\n", strlen((const char*)content), content);
//encrypt content
aes_encrypt(content,strlen((const char*)content), en, &len, (unsigned char*)key);
//base64 encode ciphertext
int encode_str_size = EVP_EncodeBlock(base64, en, len);
printf("%d %s\n", encode_str_size, base64);
//base64 decode
int length = EVP_DecodeBlock(base64_out, base64, strlen((const char*)base64));
while(base64[--encode_str_size] == '=') length--;
//decrypt
aes_decrypt(base64_out, length, de, (unsigned char*)key);
printf("%d %s\n", strlen((const char*)de), de);
/***********************Block 2*******************************/
unsigned char msg_out[400];
unsigned char msg[400] = "6hKe8RGg+4p1N1R6Y9aaTovxLtuH115JoWUO8plrAJE=";
unsigned char result[400];
int l = EVP_DecodeBlock(msg_out, msg, strlen((const char*)msg));
if(strcmp((const char*)msg, (const char*)base64)==0) {
printf("match\n");
}
if(strcmp((const char*)en, (const char*)msg_out)==0) {
printf("match\n");
}
while(msg[--encode_str_size] == '=') l--;
aes_decrypt(msg_out, l, result, (unsigned char*)key);
printf("%d %s\n", strlen((const char*)result), result);
return 0;
}
在 main 函数的块 1 中,我加密、base64 编码、base64 解码、解密,然后得到与原来完全相同的字符串,并且没有产生错误。
但是,在块 2 中,我直接使用了从块 1 生成的 base64 编码字符串,经过解码和解密,但在 result = EVP_DecryptFinal_ex(&ctx, out+len, &outl); 出现错误,即 error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length。
如果我还是打印了解密的字符串,它是loc: 123.2132412, -39.123142^D^D^D^D,最后附加了四个'^D'。我比较了字符串,都打印了match,这意味着从base64解码的密文与块1中的(en)相同。 (注意:相同的密钥,相同的 IV)
任何想法为什么它失败了?
【问题讨论】:
-
您是否尝试在 aes_encryt 中不使用
if(inl != test<<4)测试?为了始终调用EVP_EncryptFinal_ex函数。 -
@JoëlHecht 加密部分实际上运行良好。我尝试删除 if 条件,遇到加密失败
-
检查您的 openSSL 版本。从 1.1.0 开始,您不能再使用
EVP_CIPHER_CTX ctx;作为具有自动存储持续时间的变量。这种类型以及更多类型被制成不透明类型。您现在必须声明一个指针,例如EVP_CIPHER_CTX *ctx;并使用ctx = EVP_CIPHER_CTX_new();为上下文分配参见 EVP_MD_CTX "error: storage size of 'ctx' isn't known"