使用openssl c / c ++ API解密失败

时间:2018-02-13 13:43:09

标签: c++ openssl

我使用命令行中的openssl创建一个文件。让我们说:

  回声'foobar'| openssl enc -aes-128-cbc -e -pass pass:testing>   样品

我可以解密这个

  

猫样品| openssl enc -aes-128-cbc -d -pass pass:testing

工作正常。

现在我想使用openssl c / c ++ API解密该文件,但我无法做到这一点。我试图像这样解密

#include <fstream>
#include <memory>
#include <string>

#include <openssl/err.h>
#include <openssl/evp.h>

using EVP_CIPHER_CTX_free_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>;

int main(int argc, char* argv[])
{

    ERR_load_crypto_strings();

    EVP_add_cipher(EVP_aes_128_cbc());

    std::string l_key{"testing"};
    std::string l_ctext{};

    std::ifstream l_file("sample", std::ios::binary | std::ios::in | std::ios::ate);

    if(l_file.is_open())
    {
      std::streampos l_size = l_file.tellg();
      char * lp_buffer = new char[l_size];

      l_file.seekg(0, std::ios::beg);
      l_file.read(lp_buffer, l_size);
      l_ctext.append(lp_buffer, l_size);  

      delete lp_buffer;
      l_file.close();
    }

    std::string l_rtext;

    EVP_CIPHER_CTX_free_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);

    if(1 != EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL,
                               (const unsigned char*)l_key.c_str(), NULL));
      ERR_print_errors_fp(stdout);

    int l_len;

    if(1 != EVP_DecryptUpdate(ctx.get(), (unsigned char*)&l_rtext[0], &l_len,
                              (const unsigned char*)l_ctext.data(),
                              l_ctext.size()))
      ERR_print_errors_fp(stdout);

    if(1 != EVP_DecryptFinal_ex(ctx.get(), (unsigned char*)&l_rtext[0] + l_len,
                                &l_len))
      ERR_print_errors_fp(stdout);

    ERR_free_strings();

    exit(0);
}

然而,对EVP_DecryptFinal_ex的最后一次调用失败了

140559955420968:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:596:

此代码大部分基于openssl API附带的示例。我究竟做错了什么?我在EVP_DecryptInit_ex中将IV设置为NULL,因为据我所知,只要我多次不使用密钥,这是可以接受的。

所有这些都在带有GCC的Fedora机器上

1 个答案:

答案 0 :(得分:1)

我有点弄清楚我做错了什么。

  • 命令行'openssl enc'命令使用默认盐,我上面的代码没有查找。所以(而不是尝试使用'-naltalt'选项)我从加密字符串中删除前16个字节,并将其中的最后8个字节用作盐。
  • 我将密码作为“密钥”提供给EVP方法。似乎'openssl enc'没有这样做,因此需要使用salt和密码来创建密钥和IV(而不是使用NULL,这就是我所做的)。
  • 上述代码中存在错误,l_rtext需要resize()来反映添加字符的事实。