c++ - AES/CTR 解密使用 Crypto++ 意外停止?

标签 c++ encryption aes crypto++

我正在尝试使用 AES 加密和解密字节数组( vector<unsigned char> ) Crypto++ 库 .加密工作正常。

我的函数生成一个随机 IV 并将其放在加密数据的前面。解密当然是读取IV。我修改了来自 this 的代码答案,所以它适用于我的 vector 和点击率/无填充。

程序在 stfDecryptor.Put(...) 行崩溃.一开始以为是数据或IV读取不正确,但经过检查,事实并非如此。

我希望我在这里犯了一个非常明显的错误。

谢谢你们 :)

类调用:

//The code is not clean, i want to get it working first and then clean it up. 
auto key = Helper::RandomBytes(16); //returns "byte Array" with random Bytes
auto data = Helper::UTF8String2ByteArray("HELLO WORLD!");
auto encrypted = AESCrypt::encrypt(key, data);
cout << Helper::ByteArray2HexString(key);
cout << "\r\n";
cout << Helper::ByteArray2HexString(data);
cout << "\r\n";
cout << Helper::ByteArray2HexString(encrypted);
cout << "\r\n";    
auto decrypted = AESCrypt::decrypt(key, encrypted);
auto clear = Helper::ByteArray2UTF8String(decrypted);

类(class):
vector<unsigned char> AESCrypt::encrypt(vector<unsigned char> key_, vector<unsigned char> data)
{
    vector<unsigned char> iv_ = Helper::RandomBytes(16); //returns "byte Array" with random Bytes

    byte key[AES::DEFAULT_KEYLENGTH], iv[AES::BLOCKSIZE];

    for (size_t i = 0; i < AES::DEFAULT_KEYLENGTH; i++)
        key[i] = key_[i];
    for (size_t i = 0; i < iv_.size(); i++)
        iv[i] = iv_[i];

    AES::Encryption aesEncryption(key, AES::DEFAULT_KEYLENGTH);
    CTR_Mode_ExternalCipher::Encryption ctrEncryption(aesEncryption, iv);

    vector<unsigned char> encrypted;
    StreamTransformationFilter stfEncryptor(
        ctrEncryption,
        new VectorSink(encrypted),
        BlockPaddingSchemeDef::NO_PADDING);

    stfEncryptor.Put((const byte*)data.data(), data.size());
    stfEncryptor.MessageEnd();

    vector<unsigned char> output(encrypted.size() + 16);

    for (size_t i = 0; i < 16; i++)
        output[i] = iv[i];
    for (size_t i = 0; i < encrypted.size(); i++)
        output[16 + i] = encrypted[i];

    return output;
}

vector<unsigned char> AESCrypt::decrypt(vector<unsigned char> key_, vector<unsigned char> data_)
{    
    byte key[AES::DEFAULT_KEYLENGTH], iv[AES::BLOCKSIZE];
    for (size_t i = 0; i < AES::DEFAULT_KEYLENGTH; i++)
        key[i] = key_[i];
    for (size_t i = 0; i < 16; i++)
        iv[i] = data_[i];

    vector<unsigned char> data(data_.size() - 16);
    for (size_t i = 0; i < data.size(); i++)
    {
        data[i] = data_[16 + i];
    }

    AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
    CTR_Mode_ExternalCipher::Decryption ctrDecryption(aesDecryption, iv);

    vector<unsigned char> decrypted;
    StreamTransformationFilter stfDecryptor(
        ctrDecryption,
        new VectorSink(decrypted),
        BlockPaddingSchemeDef::NO_PADDING);

    stfDecryptor.Put((const byte*)data.data(), data.size()); //this is where it crashes
    stfDecryptor.MessageEnd();

    return decrypted;

}

这是 CallStack 的图片:

enter image description here

这是它在 Crypto++ 库中停止的行:

CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation());

最佳答案

This is the line where it stopps inside the CryptoPP Libary:

CRYPTOPP_ASSERT(m_cipher->IsForwardTransformation());


计数器模式 (CTR) 使用前向转换进行加密和解密。 “前向转换”是指加密。 key 流是通过对 IV/计数器进行加密而生成的,然后将 key 流与明文或密文进行异或运算。

你应该改变这个:
AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
CTR_Mode_ExternalCipher::Decryption ctrDecryption(aesDecryption, iv);

对此:
AES::Encryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
CTR_Mode_ExternalCipher::Decryption ctrDecryption(aesDecryption, iv);

注意计数器模式解密使用加密器。

维基有一个计数器模式的例子,我们把这个问答作为外部密码例子的一部分。另见 CTR Mode在 Crypto++ 维基上。

这里是复制器。

$ cat test.cxx
#include "cryptlib.h"
#include "secblock.h"
#include "filters.h"
#include "modes.h"
#include "aes.h"

#include <iostream>
#include <string>

int main (int argc, char* argv[])
{
    using namespace CryptoPP;

    SecByteBlock key(16), iv(16);
    std::memset(key, 0xff, key.size());
    std::memset( iv, 0x88,  iv.size());

    std::string message, encrypted, decrypted;
    message = "Now is the time for all good men "
        "to come to the aide of their country.";

    AES::Encryption aesEncryption(key, key.size());
    CTR_Mode_ExternalCipher::Encryption ctrEncryption(aesEncryption, iv);

    StreamTransformationFilter stfEncryptor(
        ctrEncryption, new StringSink(encrypted));

    stfEncryptor.Put((const byte*)&message[0], message.size());
    stfEncryptor.MessageEnd();

    AES::Encryption aesDecryption(key, key.size());
    CTR_Mode_ExternalCipher::Decryption ctrDecryption(aesDecryption, iv);

    StreamTransformationFilter stfDecryptor(
        ctrDecryption, new StringSink(decrypted));

    stfDecryptor.Put((const byte*)&encrypted[0], encrypted.size());
    stfDecryptor.MessageEnd();

    std::cout << "Message: " << message << std::endl;
    std::cout << "Recovered: " << decrypted << std::endl;

    return 0;
}

和:

$ g++ -g2 -O1 test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Message: Now is the time for all good men to come to the aide of their country.
Recovered: Now is the time for all good men to come to the aide of their country.

StreamTransformationFilter stfEncryptor(
    ctrEncryption,
    new VectorSink(encrypted),
    BlockPaddingSchemeDef::NO_PADDING);


对于计数器模式,不需要 BlockPaddingSchemeDef::NO_PADDING .它是计数器模式的默认值。

虽然不明显,但在 BlockPaddingScheme 的文档中有所说明。在手册中:

DEFAULT_PADDING means PKCS_PADDING if cipher.MandatoryBlockSize() > 1 && cipher.MinLastBlockSize() == 0, which holds for ECB or CBC mode. Otherwise, NO_PADDING for modes like OFB, CFB, CTR, CBC-CTS.

关于c++ - AES/CTR 解密使用 Crypto++ 意外停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59323973/

相关文章:

c# - AES 双向加盐加密

ios - 在 objective-c 中的 UIIImageView 上显示加密图像

c++ - 类中未初始化字段的值

c# - 大文件 AES 加密

c++ - 如何复制只有两个迭代器的数据?

c - C 语言中有 crypt 函数吗?或者我必须自己构建该功能?

node.js - NodeJS 如何使用 crypto-js 或使用自定义 key 大小、iv、模式和填充以 UTF8 编码的加密包来加密(AES 算法)数据

java - 将Java解密代码迁移到Golang

c++ - QAction 的 vector 未编译

c++ - 用于 win32、linux、mac 的 POSIX C 包装器