C中的OpenSSL:应用程序运行第二次解密后,结果的前16个字节为垃圾

时间:2018-09-22 14:17:55

标签: c++ c encryption openssl aes

我按照here的说明在C中使用OpenSSL实现了简单的文件加密/解密。 我并不需要真正安全(只是希望文件在驱动器上不易读取),密钥在应用程序中进行了硬编码,并且在从驱动器中读取加密文件后,我对其进行了解密。 / p>

在第一次调用时,decryptFileAsBytes函数将正确的解密文件作为字节向量返回。在第二次调用(在同一应用程序内运行)中,结果的前16个字节为垃圾,其余部分正确。这与我使用的密钥大小(128位)有关吗?

static bool decryptFileAsBytes(std::string filename, unsigned char *ckey, unsigned char *ivec, std::vector<unsigned char> &fileBytes)
{
    std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
    if (ifs.fail())
        return false;

    std::ifstream::pos_type pos = ifs.tellg();
    fileBytes.resize(pos);
    ifs.close();

    FILE *ifp;
    if (fopen_s(&ifp, filename.c_str(), "rb") != NULL)
        return false;

    int bytesRead;
    unsigned char indata[AES_BLOCK_SIZE];
    unsigned char *writePtr = fileBytes.data();

    /* data structure that contains the key itself */
    AES_KEY key;

    /* set the encryption key */
    AES_set_encrypt_key(ckey, 128, &key);

    /* set where on the 128 bit encrypted block to begin encryption*/
    int num = 0;

    while (1)
    {
        bytesRead = fread(indata, 1, AES_BLOCK_SIZE, ifp);

        AES_cfb128_encrypt(indata, writePtr, bytesRead, &key, ivec, &num, AES_DECRYPT);
        writePtr += bytesRead;

        if (bytesRead < AES_BLOCK_SIZE)
            break;
    }
    if (fclose(ifp) != NULL)
        return false;

    return true;
}

作为解决此问题的替代方法,我欢迎提出一种解决上述问题的简单建议(以不防弹的方式“加密”驱动器上的文件,以使其不易读取,但应用程序可以对其解密)。

1 个答案:

答案 0 :(得分:1)

问题可能是您没有为后续的解密操作保留原始的初始化向量。

随着AES加密/解密操作的发展,该内存将更新以继续后续帧。如果您对代码进行检测,就会看到,每个加密/解密帧通过API时,ivec都会更改。

如果您要做的只是混淆(例如,应用程序中有静态密钥),我的建议是执行以下操作:

  1. 请勿将ivec传递给加密器或解密器。
  2. 相反,在加密时,使用RAND_bytes生成随机ivec。在继续文件内容之前,将ivec存储为 first 数据块。
  3. 解密时,读取第一个数据块以准备ivec。
  4. 然后,照常解密文件的其余部分。

好处是:

  1. 对文件的每次加密都会根据初始随机ivec创建不同的字节表示形式。例如。如果您对文件进行两次加密,则加密后的字节数将不相同
  2. 您不再需要在代码的其他地方使用静态ivec。该文件包含它作为第一数据块。

只是一个建议。无关,我更喜欢EVP加密接口,并建议值得一看。