AES / GCM с GunZip, не может правильно распаковать

РЕДАКТИРОВАТЬ Я еще раз перефразировал вопрос и представил МИНИМАЛЬНЫЙ рабочий пример, который может воспроизвести ошибку.

Я пытаюсь использовать GCM для шифрования файлов. Моя основа для подчеркивания — Qt. Идея заключается в следующем:

  1. загрузить sourceFile, например a.jpg
  2. зашифровать файл в режиме GCM как PDATA
  3. в один байт хранилища ADATA (на данный момент, в реальном приложении это будет больше с такой информацией, как IV, имя оригинального файла и т. д.)
  4. добавить ADATA в зашифрованный файл

  5. загрузить зашифрованный файл и извлечь ADATA / PDATA / MAC

  6. передать эти данные в правильном порядке в AuthenticatedDecryptionFilter и ожидать, что расшифрованный файл будет сохранен в FileSink

Мне нужен цикл, который проходит через незашифрованный файл и закачивает файл в AuthenticatedEncryptionFilter, так как мне нужно проверить isAlive для целей многопоточности в реальном приложении. Поэтому я не могу использовать простую конвейерную обработку и мне приходится просматривать данные вручную в циклах.

Теперь к проблеме

Сбой проверки хэша в приведенном ниже коде (исключение выдается при дешифровании)

#include <qdebug.h>
#include <CryptoPP/cryptlib.h>
#include <CryptoPP/gcm.h>
#include <CryptoPP/aes.h>
#include <CryptoPP/filters.h>
#include <CryptoPP/files.h>
#include <CryptoPP/gzip.h>
#include <qfile.h>
#include <qfileinfo.h>using namespace CryptoPP;
using namespace std;
int main(int argc, char *argv[])
{

byte * key = new byte[16];
byte * iv = new byte[16];

memset(key, 0, 16);
memset(iv, 0, 16);

const int TAG_SIZE = 16;
const int BUFFER_SIZE = 4096;

byte keyLength = 16;
byte blockSize = 16;

const char * sourceFileName = "C:\\Users\\Tomas\\Documents\\Visual Studio 2013\\Projects\\testgcm\\Win32\\Debug\\source.jpg";
const char * sourceFileName2 = "C:\\Users\\Tomas\\Documents\\Visual Studio 2013\\Projects\\testgcm\\Win32\\Debug\\source2.jpg";
const char * destFileName = "C:\\Users\\Tomas\\Documents\\Visual Studio 2013\\Projects\\testgcm\\Win32\\Debug\\source.jpg.enc";try
{

GCM< AES >::Encryption e;
e.SetKeyWithIV(key, keyLength, iv, blockSize);

AuthenticatedEncryptionFilter ef(e,
new FileSink(destFileName), false, TAG_SIZE
);

// AuthenticatedEncryptionFilter::ChannelPut
//  defines two channels: "" (empty) and "AAD"//   channel "" is encrypted and authenticated
//   channel "AAD" is authenticated// this is the block for ADATA
QByteArray adata;
adata.append((char)1);

ef.ChannelPut("AAD", (const byte *)adata.data(), adata.size());
ef.ChannelMessageEnd("AAD");

FileStore fs(sourceFileName);

int mr = 0;

while (mr = fs.MaxRetrievable()){
fs.TransferTo(ef, BUFFER_SIZE,"");
}

ef.ChannelMessageEnd("");

// append ADATA to encrypted file

QFile file(QString::fromStdString(destFileName));
file.open(QIODevice::Append);

file.write(adata);

file.close();

// HELP: is the encrypted file in this format now? ENC_TEXT||MAC(TAG_SIZE)||HEADER(1)}
catch (CryptoPP::BufferedTransformation::NoChannelSupport& e)
{
// The tag must go in to the default channel:
//  "unknown: this object doesn't support multiple channels"cerr << "Caught NoChannelSupport..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
{
// Pushing PDATA before ADATA results in:
//  "GMC/AES: Update was called before State_IVSet"cerr << "Caught BadState..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
catch (CryptoPP::InvalidArgument& e)
{
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
}

// DECRYPTIONtry
{

// now extract ADATA and MAC from enc file
QFile file(QString::fromStdString(destFileName));
file.open(QIODevice::ReadOnly);
file.seek(file.size() - 1);

// ADATA
QByteArray adata = file.read(1);

// exract MAC

file.seek(file.size() - 1 - TAG_SIZE);
QByteArray mac = file.read(TAG_SIZE);

GCM< AES >::Decryption d;
d.SetKeyWithIV(key, keyLength, iv);// Object will not throw an exception
//  during decryption\verification _if_
//  verification fails.

AuthenticatedDecryptionFilter df(d, new FileSink(sourceFileName2),
AuthenticatedDecryptionFilter::MAC_AT_BEGIN |
AuthenticatedDecryptionFilter::THROW_EXCEPTION, TAG_SIZE);df.ChannelPut("", (const byte*)mac.data(), mac.size());

// The order of the following calls are important
df.ChannelPut("AAD", (const byte*)adata.data(), adata.size());

// open enc file
FileStore fs(destFileName);// when we read the file, we dont care for the ADATA and TAG, so we omit it
int omitSize = (adata.size() + mac.size());

// max retrievable (for FileStore this is how many bytes are not read yet)
int mr = 0;

// get part without tag and footer
while (((mr = fs.MaxRetrievable()) > omitSize)){
mr = ((mr - omitSize) < BUFFER_SIZE) ? (mr - omitSize) : BUFFER_SIZE;
fs.TransferTo(df, mr, "");
}

// we pumped teh whole filestore into df. it was supposed to be pumping it to GUnzip and then to FileSink

// and signal this is all
df.ChannelMessageEnd("AAD");
df.ChannelMessageEnd("");}
catch (CryptoPP::InvalidArgument& e)
{
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
{
// Pushing PDATA before ADATA results in:
//  "GMC/AES: Update was called before State_IVSet"cerr << "Caught BadState..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
catch (CryptoPP::HashVerificationFilter::HashVerificationFailed& e)
{
cerr << "Caught HashVerificationFailed..." << endl;
cerr << e.what() << endl;
cerr << endl;
}}

Я подозреваю, что неправильно передаю информацию в расшифровщик, но следую официальный пример CryptoPP.

Пожалуйста помоги,
Спасибо

1

Решение

Это было тривиально в конце. ВСЕГДА УБЕДИТЕСЬ, ЧТО ВЫ ПРОЙДЕТЕ

GCM< AES >::Decryption d;
d.SetKeyWithIV(key, keyLength, iv, blockSize);

а также

 GCM< AES >::Encryption e;
e.SetKeyWithIV(key, keyLength, iv, blockSize);

даже если они не являются обязательными. Невыполнение этого требования приведет к неправильной расшифровке

2

Другие решения


По вопросам рекламы [email protected]