Имате проблеми с дешифрирането на добре оформен шифрован текст с помощта на Crypto++

Заден план

От около ден се боря с дешифрирането на очевидно добре оформен шифрован текст. Да приемем, че имаме следния шестнадесетичен шифрован текст, който съдържа точно 160 знака, като по този начин има 80 байта.

QString c = "1BFAC407AF0D440A2D6176C0B5D125AA96088490299AC18C74623C0EF1BB1372E554FC4150A8066220E943697BE2491D8AE13AA036B298425AC510A8A917D59EBB69708B9040AB3A84C63043EAD4AB07";
QString k = CryptoUtils::hexEncode("abc");
QString p = CryptoUtils::decrypt(c, k);

qDebug() << p;

При условие, че използваме AES 256, AFAIK, ключът трябва да е с дължина 32 байта и шифрован текст с дължина, кратна на 16 байта, като всички тези условия са изпълнени по отношение на моя код на фрагмент.

Моля, обърнете внимание, че използвам SHA256 захранване с парола за генериране на 32-байтов ключ. Така че това гарантира, че всички ключове са с дължина 32 байта.

Пълните изходни кодове на тези функция може да се намери в моето репо в GitHub (в клон Part1).


Въпросът ми

Когато искам да стартирам този код, приложението ми се срива. Ето изключението:

terminate called after throwing an instance of 'CryptoPP::InvalidCiphertext'
  what():  StreamTransformationFilter: invalid PKCS #7 block padding found
The program has unexpectedly finished.

Търсих наоколо за този проблем и разбрах, че може да се дължи на крайното \0, след като сте шифровали обикновения текст. Не можех обаче просто да разреша проблема. Моля, помогнете ми, просто ме подлудява.


person frogatto    schedule 08.12.2015    source източник
comment
Как получихте шифрования текст? Използвайки същите методи? Грешките при подпълване на PKCS#7 са единствените грешки, които могат да бъдат генерирани (освен грешките, свързани с размера на блока), те показват неправилен код, неправилен ключ или неправилни данни (и за малък шифрован текст в режим CBC, дори неправилно IV).   -  person Maarten Bodewes    schedule 09.12.2015
comment
StringSource(decodedKey, size, true, new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)));: това не е добър KBKDF, той крие проблеми с ключа и по мое скромно мнение е доста нечетлив. Ако използвате нещо различно от библиотеката, към която сочите, дешифрирането със сигурност ще се провали (освен ако същото нестандартно хеширане не се приложи в другата библиотека, разбира се).   -  person Maarten Bodewes    schedule 09.12.2015
comment
@MaartenBodewes Генерирах този шифрован текст от функцията encrypt (от този cpp файл, към който се свързах). Освен това IV винаги е 0. За ключ не мога да видя какъв е проблемът с SHA256 (просто трябва да генерирам унифициран ключ от парола и за това просто няма значение кой алгоритъм трябва да използвам).   -  person frogatto    schedule 09.12.2015


Отговори (2)


Пълните изходни кодове на тези функции могат да бъдат намерени в моето репо в GitHub

Бих направил поне тези промени:

QString CryptoUtils::encrypt(QString text, QString keyhex)
{
    ...

    // name the variable, kill the memory leak
    SHA256 sha256;
    StringSource ss1(decodedKey, size, true, new HashFilter(sha256, new ArraySink(key, AES::MAX_KEYLENGTH)));
    ...

    // name the variable
    StringSource ss2(plain, true, new StreamTransformationFilter(Encryptor, new HexEncoder(new StringSink(encrypted))));

    // verify embedded NULLs don't affect results
    QString qs = QString::fromStdString(encrypted);
    assert(qs.length() == encrypted.length());
}

И:

QString CryptoUtils::decrypt(QString text, QString keyhex)
{
    // bad karma here...
    string encrypted = text.toStdString();
    assert(encrypted.length() == text.length());
    ...

    // name the variable, kill the memory leak
    SHA256 sha256;
    StringSource ss1(decodedKey, size, true, new HashFilter(sha256, new ArraySink(key, AES::MAX_KEYLENGTH)));
    ...

    // name the variable,
    StringSource ss2(encrypted, true, new HexDecoder(new StreamTransformationFilter(Decryptor, new StringSink(plain))));

    // verify embedded NULLs don't affect results
    QString qs = QString::fromStdString(plain);
    assert(qs.length() == plain.length());
}
person jww    schedule 10.12.2015
comment
Благодаря Ви за отговора. Но проблемът беше заради моята функция hexEncode. Генерираше различни шестнадесетични кодове за идентичен вход. - person frogatto; 10.12.2015
comment
@Frogatto - Генерираше различни шестнадесетични кодове за идентичен вход - това е интересно по някакъв болезнен начин... Използвайте UTF-8; това е най-доброто за оперативна съвместимост. Или използвайте необработените байтове и нещо като HKDF, за да извлечете и разширите ентропия. - person jww; 11.12.2015

Функцията hexEncode изглежда не се държи правилно:

QString CryptoUtils::hexEncode(QString text)
{
    byte *bytearray = (byte *) text.toLatin1().data();
    int length = text.toLatin1().length();

    return hexEncode(bytearray, length);
}

Трябва да се замени с:

QString CryptoUtils::hexEncode(QString text)
{
    byte *bytearray = (byte *) text.toStdString().data();
    int length = text.length();

    return hexEncode(bytearray, length);
}
person frogatto    schedule 10.12.2015