派生用于OpenSSL AES解密的密钥和IV

时间:2019-03-24 09:28:42

标签: c openssl

我正在尝试使用C代码中的openssl函数进行AES解密操作,但失败了。

使用openssl命令行工具,我可以成功解密blob。

openssl enc -d -p -aes-256-cbc -md md5 -in encrypted_file -out clear_file -pass file:./key_file -v

上面的命令工作正常。

但是当我使用openssl C函数执行相同操作时,它将失败。失败似乎与密码错误以及从passwd和salt导出的iv有关。

unsigned char key[32];
unsigned char iv[16];
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), salt, key_file_buf, key_size, 1, key, iv);

[key_file_buf是从key_file读取的无符号字符缓冲区。]

salt和key_file_buf的十六进制转储与命令行中使用的十六进制转储匹配。大小也正确。(以我的情况为45个字节。)

使用EVP_BytesToKey()返回错误的密钥和iv可能出什么问题了?

我已经尝试过使用iter count值进行实验,但是似乎都没有生成工作密钥和iv。我仍然假设命令行的默认迭代计数为1。

还确认,如果我用工作密钥和从命令行其余部分显示的iv覆盖从EVP_BytesToKey()和硬代码无符号字符数组返回的内容,则可以正常工作并正确解密。

有关信息,这就是其余代码的样子(从不同来源复制,在网络上提供示例)

EVP_CIPHER_CTX_new();
if(ctx == NULL) {
    printf("Error with EVP_CIPHER_CTX_new.\n");
    return;
}    

if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) {
    printf("Error initialising decrypted data.\n");
    return;
}    

if(1 != EVP_DecryptUpdate(ctx, clear_data, (int *)&interm_len, &enc_data[salt_size], enc_size)) {
    printf("Error decrypting data.\n");
    return;
}    

*clear_size = interm_len;

if(1 != EVP_DecryptFinal_ex(ctx, clear_data + interm_len, (int *)&interm_len)) {
    printf("Error decrypting data.\n");
    return;
}    
*clear_size += interm_len;

EVP_CIPHER_CTX_free(ctx);

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

终于想通了! 应该是

EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), salt, key_file_buf, (key_size-1), 1, key, iv);

如openssl文档中所述

文件:路径名 路径名的第一行是密码。如果将相同的路径名参数提供给-passin和-passout参数,则第一行将用于输入密码,下一行将用于输出密码。

我的passwd文件以换行符0x0A结尾。所以我从buf的EVP_BytesToKey()中删除了它,它返回正确的密钥&iv,并立即解密。