OpenSSL в C: после второй расшифровки при запуске приложения первые 16 байт результата являются мусором - PullRequest
0 голосов
/ 22 сентября 2018

Я реализовал простое шифрование / дешифрование файлов с помощью OpenSSL в C согласно инструкциям здесь . Мне не нужно, чтобы это было действительно безопасно (просто хочу, чтобы файлы не были легко читаемыми на диске), ключи жестко закодированы в приложении, и после считывания зашифрованных файлов с диска я расшифровываю их.

При первом вызове функция 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 голосов
/ 22 сентября 2018

Возможно, проблема в том, что вы не сохраняете исходный вектор инициализации для последующих операций дешифрования.

По мере выполнения операций шифрования / дешифрования AES эта память обновляется для продолжения с последующими кадрами.Если вы обработаете свой код, который увидите, с каждым кадром шифрования / дешифрования, проходящим через API, ivec изменяется.

Если все, что вы делаете для этого - это запутывание (например, у вас есть статический ключ в вашем приложении), я предлагаю сделать следующее:

  1. Не передавайтеivec в шифратор или дешифровщик.
  2. Вместо этого генерируйте случайный ivec, используя RAND_bytes при шифровании.Сохраните ivec как первый блок данных, прежде чем продолжить работу с содержимым файла.
  3. При расшифровке читайте первый блок данных, чтобы заполнить ваш ivec.
  4. Затем,расшифруйте оставшуюся часть файла как обычно.

Преимущества:

  1. Каждое шифрование файла создает различное представление байтов, зависящее от начального случайного ivec.Например.если вы дважды зашифруете файл, результирующие зашифрованные байты не будут такими же
  2. Вам больше не придется использовать статический ivec где-то еще в вашем коде.Файл содержит его в качестве первого блока данных.

Просто предложение.Вне зависимости, я предпочитаю интерфейс шифрования EVP и предлагаю его посмотреть.

...