首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从加密项的向量中解密任意选定的元素将导致无效的PKCS #7块错误。

从加密项的向量中解密任意选定的元素将导致无效的PKCS #7块错误。
EN

Stack Overflow用户
提问于 2020-01-02 12:50:01
回答 1查看 130关注 0票数 0

我试图在Crypto++中使用AES加密一些顺序数据。但是,我注意到随机选择加密项并解密它会导致StreamTransformationFilter:无效的PKCS #7块填充找到的

造成同样问题的简单代码如下:

代码语言:javascript
运行
复制
AESUtil aes;
std::vector<std::string> t = std::vector<std::string>();

for (int i = 0; i < 100; ++i) {
    std::string p = "a";
    auto c = aes.encrypt(p);
    t.push_back(c);
}

auto d = aes.decrypt(t[78]);

其中AESUtil如下所示:

代码语言:javascript
运行
复制
AESUtil::AESUtil() {
    this->key = CryptoPP::SecByteBlock(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
    rnd.GenerateBlock(key, key.size());

    // Generate a random IV
    this->iv = CryptoPP::SecByteBlock(CryptoPP::AES::BLOCKSIZE);
    rnd.GenerateBlock(iv, iv.size());

    this->aesEncryption = CryptoPP::AES::Encryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
    this->cbcEncryption = CryptoPP::CBC_Mode_ExternalCipher::Encryption(aesEncryption, iv);

    this->aesDecryption = CryptoPP::AES::Decryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
    this->cbcDecryption = CryptoPP::CBC_Mode_ExternalCipher::Decryption(aesDecryption, iv);
}

void AESUtil::encrypt(std::string &ciphertext, std::string &plaintext) {
    CryptoPP::StreamTransformationFilter stfEncryptor(this->cbcEncryption, new CryptoPP::StringSink(ciphertext));
    stfEncryptor.Put(reinterpret_cast<const unsigned char *>( plaintext.c_str()), plaintext.size());
    stfEncryptor.MessageEnd();
}

void AESUtil::decrypt(std::string &plaintext, std::string &ciphertext) {
    CryptoPP::StreamTransformationFilter stfDecryptor(this->cbcDecryption, new CryptoPP::StringSink(plaintext));
    stfDecryptor.Put(reinterpret_cast<const unsigned char *>( ciphertext.c_str()), ciphertext.size());
    stfDecryptor.MessageEnd();
}

std::string AESUtil::encrypt(std::string plaintext) {
    std::string ciphertext;
    //ciphertext.reserve(plaintext.size()+16);
    encrypt(ciphertext, plaintext);
    return ciphertext;
}

std::string AESUtil::decrypt(std::string ciphertext) {
    std::string plaintext;
    //plaintext.reserve(ciphertext.size()+16);
    decrypt(plaintext, ciphertext);
    return plaintext;
}

我认为这个问题被链接到字符串中的\0空终止字符,所以我将代码更改为使用十六进制(不确定它是否真的正确)。然而,这一问题仍然存在。

代码语言:javascript
运行
复制
void AESUtil::encrypt(std::string &ciphertext, std::string &plaintext) {
    CryptoPP::ByteQueue encrypted;
    CryptoPP::StreamTransformationFilter f1(this->cbcEncryption, new CryptoPP::Redirector(encrypted));

    //f1.PutWord32((uint32_t)v1.size(), BIG_ENDIAN_ORDER);
    f1.Put((const unsigned char *) plaintext.c_str(), plaintext.size());
    f1.MessageEnd();
    CryptoPP::HexEncoder encoder(new CryptoPP::StringSink(ciphertext));
    encrypted.CopyTo(encoder);
    encoder.MessageEnd();
}

void AESUtil::decrypt(std::string &plaintext, std::string &ciphertext) {
    CryptoPP::ByteQueue decrypted;
    CryptoPP::HexDecoder decoder(new CryptoPP::Redirector(decrypted));
    decoder.Put(reinterpret_cast<const unsigned char *>( ciphertext.data()), ciphertext.size());
    decoder.MessageEnd();

    CryptoPP::StreamTransformationFilter f2(this->cbcDecryption, new CryptoPP::StringSink(plaintext));
    decrypted.CopyTo(f2);
    f2.MessageEnd();
}

对于下面的代码,两个AESUtil版本都可以正常工作,没有任何问题:

代码语言:javascript
运行
复制
for (int i = 0; i < 100; ++i) {
        std::string p = "a";
        auto c = aes.encrypt(p);
        auto d = aes.decrypt(c);
    }

知道问题是什么吗?我怎样才能解决它?任何帮助都将是非常感谢的

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-16 09:55:10

我发现了这个问题。

即使MessageEnd被调用,IV也在改变,保持着对州 of AESUtil的引用。

我解决了这个问题,在加密过程中随机生成IV,并将它与密文一起存储。

如果有人感兴趣,下面是新代码:

代码语言:javascript
运行
复制
void AESUtil::encrypt(std::string &ciphertext, std::string &plaintext) {
    // Generate a random IV
    CryptoPP::SecByteBlock iv(CryptoPP::AES::BLOCKSIZE);
    this->rnd.GenerateBlock(iv, iv.size());
    //memset( iv, 0x00, CryptoPP::AES::BLOCKSIZE );

    CryptoPP::StringSink stringSink(ciphertext);

    CryptoPP::ArraySource as(iv, iv.size(), true,
                             new CryptoPP::Redirector(stringSink));

    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(this->aesEncryption, iv);

    CryptoPP::ByteQueue encrypted;
    CryptoPP::StreamTransformationFilter f1(cbcEncryption, new CryptoPP::Redirector(encrypted));

    f1.Put(reinterpret_cast<const unsigned char *>(plaintext.c_str()), plaintext.size());
    f1.MessageEnd();

    CryptoPP::HexEncoder encoder(new CryptoPP::Redirector(stringSink));
    encrypted.CopyTo(encoder);
    encoder.MessageEnd();

    std::string recovered;
    CryptoPP::StringSink sink(recovered);
    encrypted.CopyTo(sink);
}

void AESUtil::decrypt(std::string &plaintext, std::string &ciphertext) {
    CryptoPP::SecByteBlock iv(CryptoPP::AES::BLOCKSIZE);
    CryptoPP::StringSource ss(ciphertext, false /* DO NOT Pump All */);

    // Attach new filter
    CryptoPP::ArraySink as(iv, iv.size());
    ss.Attach(new CryptoPP::Redirector(as));
    ss.Pump(CryptoPP::AES::BLOCKSIZE);  // Pump first 16 bytes

    CryptoPP::StringSink stringSink(plaintext);
    CryptoPP::ByteQueue decrypted;
    CryptoPP::HexDecoder decoder(new CryptoPP::Redirector(decrypted));

    ss.Detach(new CryptoPP::Redirector(decoder));
    ss.PumpAll();

    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(this->aesDecryption, iv);
    CryptoPP::StreamTransformationFilter f2(cbcDecryption, new CryptoPP::Redirector(stringSink));
    decrypted.CopyTo(f2);
    f2.MessageEnd();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59563651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档