Редкий сбой с Crypto ++ pbkdf2 :: DeriveKey () - PullRequest
0 голосов
/ 08 ноября 2018

Я использую библиотеку CryptoPP для хеширования некоторых паролей. Приблизительно 1 в 10 раз происходит сбой в строке DeriveKey ниже с ошибкой сегмента.

Даже при использовании фиксированных параметров сбои все еще кажутся случайными. Мне интересно, если мне нужно '\ 0' на конце моих строк. Или, может быть, выходной буфер должен быть инициализирован нулями или что-то в этом роде?

В любом случае, вот код.

#include <cryptopp/aes.h>
#include <cryptopp/algparam.h>
#include <cryptopp/filters.h>
#include <cryptopp/modes.h>
#include <cryptopp/sha.h>
#include <cryptopp/pwdbased.h>

int main()
{
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256> pbkdf2;

CryptoPP::byte salt[16];

CryptoPP::byte key[32];

/* Hard coded for testing purposes */
Common::podFromHex("00f8807a289655b2a8e38cda00182a32", salt);

/* Hard coded for testing purposes */
std::string password = "a";

std::cout << "Salt: " << Common::podToHex(salt) << std::endl;
std::cout << "Salt size: " << sizeof(salt) << std::endl;
std::cout << "Password: " << password.data() << std::endl;
std::cout << "Password size: " << password.size() << std::endl;

/* Rare segfault on this line */
pbkdf2.DeriveKey(
    key, sizeof(key), 0, (CryptoPP::byte *)password.data(),
    password.size(), salt, sizeof(salt), Constants::PBKDF2_ITERATIONS
);
}

Кажется, все инициализировано правильно - операторы print каждый раз дают мне одно и то же:

Salt: 00f8807a289655b2a8e38cda00182a32
Salt size: 16
Password: a
Password size: 1

Более того - хешированный пароль пригоден для использования, если он не работает по умолчанию. Позже я использую шифрование AES, и я могу полностью расшифровать файл, и все данные, как и ожидалось.

Исходный код для производного ключа можно найти здесь, кстати: https://www.cryptopp.com/docs/ref/pwdbased_8h_source.html#l00235

Спасибо.

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Я все исправил. На самом деле это произошло не из-за какого-либо кода, перечисленного выше, а потому, что я вызывал функцию, использующую это, в обработчике сигналов.

Поскольку для его запуска требовалось немало времени (с использованием 500 000 итераций), здесь каждый раз происходил сбой, но на самом деле это было не из-за этой строки.

Я закончил тем, что исправил переворачивание флага bool в обработчике сигналов и создал отдельный поток, наблюдающий за этим флагом. Когда флаг был установлен, он вызывал деструктор, который, в свою очередь, запускал нормальный поток завершения работы, позволяя всем моим потокам завершать работу и сохранять правильно.

0 голосов
/ 08 ноября 2018

Я рискну угадать, но salt не завершено NULL. Программа, вероятно, обращается за пределами 16-го элемента массива salt:

std::cout << "Salt: " << Common::podToHex(salt) << std::endl;

Следующее выполняется несколько раз без проблем. Это ваша программа без обращений в Общую библиотеку.

Вызов std::memcpy занимает только самые левые 16 байтов строки. Это не делает преобразование. (Я только хотел убрать звонок на Common).

$ cat test.cxx

#include "cryptlib.h"
#include "filters.h"
#include "sha.h"
#include "hex.h"
#include "files.h"
#include "pwdbased.h"

#include <string>
#include <iostream>
#include <cstring>

int main()
{
    using namespace CryptoPP;

    PKCS5_PBKDF2_HMAC<SHA256> pbkdf2;

    byte salt[16], key[32];

    /* Hard coded for testing purposes */
    // Common::podFromHex("00f8807a289655b2a8e38cda00182a32", salt);
    std::memcpy(salt, "00f8807a289655b2a8e38cda00182a32", 16);

    /* Hard coded for testing purposes */
    std::string password = "a";

    // std::cout << "Salt: " << Common::podToHex(salt) << std::endl;
    std::cout << "Salt: ";
    StringSource(salt, sizeof(salt), true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    std::cout << "Salt size: " << sizeof(salt) << std::endl;
    std::cout << "Password: " << password.data() << std::endl;
    std::cout << "Password size: " << password.size() << std::endl;

    /* Rare segfault on this line */
    pbkdf2.DeriveKey(
        key, sizeof(key), 0, (byte *)password.data(),
        password.size(), salt, sizeof(salt), 10000 /*Constants::PBKDF2_ITERATIONS*/
    );

    std::cout << "Key: ";
    StringSource(key, sizeof(key), true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    return 0;
}

Скомпилировано и выполнено с:

$ g++ -DNDEBUG -g2 -O3 test.cxx -o test.exe ./libcryptopp.a
$ ./test.exe
Salt: 30306638383037613238393635356232
Salt size: 16
Password: a
Password size: 1
Key: F88BA6947B802C66F7E7A2BC0099AFD92C81DC293E3CC48C2DA3FA75E27ECE6B
...