Повторное шифрование файла зашифрованных данных создает дешифрованный вывод - PullRequest
1 голос
/ 02 июля 2019

Я написал функцию шифрования с использованием библиотеки Crypto ++, функция ведет себя правильно, когда шифрование файла выполняется впервые. Если тот же зашифрованный файл снова передается для шифрования, генерируется вывод, который включает зашифрованные и дешифрованные данные.

bool EncryptDataFile(const char* inputFile, const char* outputFile)
{
  try
  {
    std::vector<byte> key = HexDecoding(PASSCODE);
    std::vector<byte> iv = HexDecoding(INITIALIZATION_VECTOR);

    GCM<AES>::Encryption encryptor;
    encryptor.SetKeyWithIV(key.data(), key.size(), iv.data(), iv.size());

    FileSource fs(inputFile, true,
        new AuthenticatedEncryptionFilter(encryptor,
            new FileSink(outputFile), false, TAG_SIZE));
  }

  catch(...)
  {
    return false;
  }

  return true;
}

input.txt:

Privacy and Security

Output1.txt - первый выход шифрования:

{)ªei ?ñìCzN[hç&Ää€|Ùrñ½…
Ä

Вход «Output1.txt», Выход «Output2.txt» - шифрование во второй раз:

Privacy and Security]®Ÿwþñ úeS„£Fpä40WL ,ÈR¯M 

Выявлены исходные данные. Не уверен, что здесь не хватает.

1 Ответ

0 голосов
/ 03 июля 2019

Если тот же зашифрованный файл снова передается для шифрования, генерирует вывод, который включает в себя зашифрованные и дешифрованные данные.

Если я правильно разбираю вещи, вместо этого вы говорите m ≅ Enc(Enc(m))c = Enc(Enc(m)) в вашей схеме шифрования.Это одна из причин, по которой вам следует избегать разработки собственной схемы.

Это может произойти в нескольких сценариях, например, при использовании потокового шифра или блочного шифра в режиме счетчика при повторном использовании ключа и iv.

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


std::vector<byte> key = HexDecoding(PASSCODE);
std::vector<byte> iv = HexDecoding(INITIALIZATION_VECTOR);

Вероятно, это ваша проблема.Вам необходимо использовать разные контексты безопасности для каждого сообщения или операции шифрования.


Вот как это исправить.Вы используете функцию получения ключа для получения различных параметров безопасности для каждого шифрования.В приведенном ниже коде 32-байтовый ключ разделен на два 16-байтовых ключа.То же самое относится к iv.Первое шифрование использует key+0 и iv+0;и второе шифрование использует key+16 и iv+16.

cryptopp$ cat test.cxx
#include "cryptlib.h"
#include "filters.h"
#include "files.h"
#include "aes.h"
#include "gcm.h"
#include "hex.h"
#include "hkdf.h"
#include "sha.h"

#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;

    std::string password = "super secret password";
    SecByteBlock key(32), iv(32);

    HKDF<SHA256> hkdf;
    hkdf.DeriveKey(key, key.size(),
                   (const byte*)password.data(), password.size(),
                   NULL, 0,  // salt
                   (const byte*)"key derivation", 14);

    hkdf.DeriveKey(iv, iv.size(),
                   (const byte*)password.data(), password.size(),
                   NULL, 0,  // salt
                   (const byte*)"iv derivation", 13);


    std::string m = "Yoda said, Do or do not. There is no try.";
    std::string c1, c2;

    GCM<AES>::Encryption encryptor;

    encryptor.SetKeyWithIV(key, 16, iv, 16);
    StringSource(m, true, new AuthenticatedEncryptionFilter(
                 encryptor, new StringSink(c1)));

    encryptor.SetKeyWithIV(key+16, 16, iv+16, 16);
    StringSource(c1, true, new AuthenticatedEncryptionFilter(
                 encryptor, new StringSink(c2)));    

    std::cout << "Hex(m):" << std::endl;
    StringSource(m, true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    std::cout << "Hex(Enc(m)):" << std::endl;
    StringSource(c1, true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    std::cout << "Hex(Enc(Enc(m))):" << std::endl;
    StringSource(c2, true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    return 0;
}

Вот прогон программы:

cryptopp$ ./test.exe
Hex(m):
596F646120736169642C20446F206F7220646F206E6F742E205468657265206973206E6F20747279
2E
Hex(Enc(m)):
D4A9063DE7400E90627DE90D16346DC5A99740C55F6FEE092A99071F55F1BDB25A72B7422126CCC4
09B5B5C0076E39EBF7256D5DC3151A738D
Hex(Enc(Enc(m))):
83A459F2D4A1627624AF162590465AC705C8AC0F4D915E4A4A9D300156C5F9E042CAA47903353F0A
A1FAE408D5747DD223AC4F9AEF3C320EEF7E79E08AB2C6FBEAE7A3A5B4978C45C7

Я думаю, что ваша схема имеет некоторые дополнительные проблемы,Например, если вы шифруете сообщение «Атака на рассвете!» несколько раз, то вы получаете один и тот же зашифрованный текст при каждом запуске.Это утечка информации, и ей не хватает неразличимости зашифрованного текста.

Я думаю, что вам следует избегать вашей схемы и использовать Схему шифрования на основе эллиптических кривых (ECIES) .Это позволяет избежать большинства скрытых проблем в вашей схеме и достигает IND-CCA2 .

Недостатком ECIES является то, что вам приходится управлять парой открытых / закрытых ключей.Это не большой недостаток, хотя.Вы уже управляете паролем и iv, поэтому переход от пароля к закрытому ключу не намного больше работы.

...