使用 Crypto++ 解密格式正确的密文时遇到问题

Having trouble decrypting a well-formed cipher text using 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 字节。

Full source codes 这些功能可以在我的 GitHub(在分支 Part1)的回购协议中找到。


我的问题

当我想要 运行 这段代码时,我的应用程序崩溃了。这是例外情况:

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

我搜索了一下这个问题,发现这可能是因为加密纯文本后尾随 [=12=]。但是,我不能只解决问题。请帮助我,这让我发疯。

Full source codes of those function can be found on my repo on 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());
}

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);
}