我正在使用CryptoPP库对一些密码进行哈希处理。大约有十分之一的次数,它在下面的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
);
}
一切似乎都已正确初始化-每次打印语句都会给我完全相同的东西:
Salt: 00f8807a289655b2a8e38cda00182a32
Salt size: 16
Password: a
Password size: 1
此外-散列密码不分段时可以使用。稍后我将使用AES加密,并且可以完全解密该文件,并且所有数据均符合预期。
可以通过以下方式找到派生密钥的源代码:https://www.cryptopp.com/docs/ref/pwdbased_8h_source.html#l00235
谢谢。
答案 0 :(得分:3)
我很冒险,但是salt
并非以NULL结尾。该程序可能正在访问salt
数组的第16个元素之外:
std::cout << "Salt: " << Common::podToHex(salt) << std::endl;
以下命令可以多次执行而不会出现问题。它是您的程序,而不是对Common库的调用。
对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
答案 1 :(得分:0)
我最终解决了这个问题。这实际上不是由于上面列出的任何代码,而是因为我在信号处理程序中使用此函数调用了函数。
由于运行(使用500,000次迭代)需要花费相当长的时间,因此每次似乎都在此处崩溃,但这实际上不是由于此行引起的。
我最终通过在信号处理程序中翻转bool标志来修复它,并有一个单独的线程监视该标志。设置该标志后,它调用了析构函数,该析构函数又触发了正常的关闭流程,从而允许我所有的线程关闭并正确保存。