gpt4 book ai didi

c++ - 流转换过滤器 : invalid PKCS #7 block padding found using AES decryption

转载 作者:行者123 更新时间:2023-11-30 04:46:09 32 4
gpt4 key购买 nike

我正在尝试使用 crypto++ 执行 AES 解密图书馆。我有一个加密文件,其前 8 个字节是文件长度,随后的 16 个字节是初始化 vector ,其余数据是感兴趣的数据。我也有我的 key 的字符串表示(我使用 SHA256 对其进行哈希处理)

尝试执行 AES 解密时出现以下错误: StreamTransformationFilter: invalid PKCS #7 block padding found

我正在使用以下 C++ 代码:

std::string keyStr = "my_key";
std::string infilePath = "my/file/path";


CryptoPP::SHA256 hash;
unsigned char digest[CryptoPP::SHA256::DIGESTSIZE];

hash.CalculateDigest( digest, reinterpret_cast<const unsigned char*>(&keyStr[0]), keyStr.length() );
auto key = CryptoPP::SecByteBlock(digest, CryptoPP::SHA256::DIGESTSIZE);

std::ifstream fin(infilePath, std::ifstream::binary);

// First 8 bytes is the file size
std::vector<char> fileSizeVec(8);
fin.read(fileSizeVec.data(), fileSizeVec.size());

// Read the next 16 bytes to get the initialization vector
std::vector<char> ivBuffer(16);
fin.read(ivBuffer.data(), ivBuffer.size());
CryptoPP::SecByteBlock iv(reinterpret_cast<const unsigned char*>(ivBuffer.data()), ivBuffer.size());

// Create a CBC decryptor
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption;
decryption.SetKeyWithIV(key, sizeof(key), iv);

CryptoPP::StreamTransformationFilter decryptor(decryption);

std::vector<char> buffer(CHUNK_SIZE, 0);

while(fin.read(buffer.data(), buffer.size())) {
CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), buffer.size());
decryptor.Put(tmp, tmp.size());
}

decryptor.MessageEnd();
size_t retSize = decryptor.MaxRetrievable();

std::vector<char> decryptedBuff;
decryptedBuff.resize(retSize);

decryptor.Get(reinterpret_cast<CryptoPP::byte*>(decryptedBuff.data()), decryptedBuff.size());

我不确定是什么导致了我的错误。我正在处理以下 python 代码。当我使用相同的输入文件运行 python 代码时,它成功地解密了该文件。

def decrypt_file(in_filename, out_filename=None):
key = hashlib.sha256(PASSWORD).digest()
"""loads and returns the embedded model"""
chunksize = 24 * 1024
if not out_filename:
out_filename = os.path.splitext(in_filename)[0]

with open(in_filename, 'rb') as infile:
# get the initial 8 bytes with file size
tmp = infile.read(8)
iv = infile.read(16)
decryptor = AES.new(key, AES.MODE_CBC, iv)
string = b''
# with open(out_filename, 'wb') as outfile:
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
string += decryptor.decrypt(chunk)
return string

除了解决错误之外,我还喜欢一些关于如何改进的通用 C++ 编码反馈。

提前致谢!

编辑:看起来我并没有一直读取输入文件(因为最后一个 block 的长度小于 CHUNK_SIZE )。下面的代码现在读取整个文件,但我仍然遇到同样的问题。我还确认了 IVkey与 python 代码生成的完全匹配。

 // Get the length of the file in bytes
fin.seekg (0, fin.end);
size_t fileLen = fin.tellg();
fin.seekg (0, fin.beg);

std::vector<char> buffer(CHUNK_SIZE, 0);
size_t readSize = CHUNK_SIZE;

while(fin.read(buffer.data(), readSize)) {
CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), CHUNK_SIZE);
decryptor.Put(tmp, tmp.size());

std::fill(buffer.begin(), buffer.end(), 0);

size_t bytesReamining = fileLen - fin.tellg();
readSize = CHUNK_SIZE < bytesReamining ? CHUNK_SIZE : bytesReamining;

if (!readSize)
break;
}
}

请注意,我已将此行作为 CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), CHUNK_SIZE); 进行了尝试和 CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), readSize); (使用 CHUNK_SIZE 垫与 0 )

最佳答案

I have an encrypted file whose first 8 bytes are the filelength, subsequent 16 bytes are the initialization vector, and the remaining data is the data of interest...

我想我会切入正题,向您展示使用 Crypto++ 库做事的更简单方法。 key 和 iv 是硬编码的,以简化代码。该示例不需要推导。顺便说一下,如果 Python 有它,你应该考虑使用 HKDF用于推导 AES key 和 iv。 HKDF 具有可证明的安全属性。

Crypto++ 为您处理分块。您不需要明确执行它;见Pumping Data在 Crypto++ wiki 上。

我相信 Python 代码具有潜在的填充 oracle,因为使用了没有 MAC 的 CBC 模式。您可以考虑添加 MAC 或使用 Authenticated Encryption运作模式。

#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "modes.h"
#include "files.h"
#include "aes.h"
#include "hex.h"

#include <string>
#include <iostream>

const std::string infilePath = "test.dat";

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

const byte key[16] = {
1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4
};
const byte iv[16] = {
8,7,6,5, 8,7,6,5, 8,7,6,5, 8,7,6,5
};
const byte data[] = // 70 characters
"Now is the time for all good men to come to the aide of their country.";

HexEncoder encoder(new FileSink(std::cout));
std::string message;

// Show parameters
{
std::cout << "Key: ";
StringSource(key, 16, true, new Redirector(encoder));
std::cout << std::endl;

std::cout << "IV: ";
StringSource(iv, 16, true, new Redirector(encoder));
std::cout << std::endl;

std::cout << "Data: ";
StringSource(data, 70, true, new Redirector(encoder));
std::cout << std::endl;
}

// Write sample data
{
FileSink outFile(infilePath.c_str());
word64 length = 8+16+70;

outFile.PutWord64(length, BIG_ENDIAN_ORDER);
outFile.Put(iv, 16);

CBC_Mode<AES>::Encryption enc;
enc.SetKeyWithIV(key, 16, iv, 16);

StringSource(data, 70, true, new StreamTransformationFilter(enc, new Redirector(outFile)));
}

// Read sample data
{
FileSource inFile(infilePath.c_str(), true /*pumpAll*/);

word64 read, l;
read = inFile.GetWord64(l, BIG_ENDIAN_ORDER);
if (read != 8)
throw std::runtime_error("Failed to read length");

SecByteBlock v(16);
read = inFile.Get(v, 16);
if (read != 16)
throw std::runtime_error("Failed to read iv");

CBC_Mode<AES>::Decryption dec;
dec.SetKeyWithIV(key, 16, v, 16);

SecByteBlock d(l-8-16);
StreamTransformationFilter f(dec, new ArraySink(d, d.size()));
inFile.CopyTo(f);
f.MessageEnd();

std::cout << "Key: ";
StringSource(key, 16, true, new Redirector(encoder));
std::cout << std::endl;

std::cout << "IV: ";
StringSource(v, 16, true, new Redirector(encoder));
std::cout << std::endl;

std::cout << "Data: ";
StringSource(d, d.size(), true, new Redirector(encoder));
std::cout << std::endl;

message.assign(reinterpret_cast<const char*>(d.data()), d.size());
}

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

return 0;
}

运行程序结果:

$ g++ test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Key: 01020304010203040102030401020304
IV: 08070605080706050807060508070605
Data: 4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F2063
6F6D6520746F207468652061696465206F6620746865697220636F756E7472792E

Key: 01020304010203040102030401020304
IV: 08070605080706050807060508070605
Data: 4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F2063
6F6D6520746F207468652061696465206F6620746865697220636F756E7472792E

Message: Now is the time for all good men to come to the aide of their country.

在此 Stack Overflow 问题之前,Crypto++ 库不提供 PutWord64GetWord64。与 Python 等库的互操作对项目很重要,因此将它们添加到 Commit 6d69043403a9。和 Commit 8260dd1e81c3 .它们将成为 Crypto++ 8.3 版本的一部分。

如果您使用的是 Crypto++ 8.2 或更低版本,则可以使用以下代码执行 64 位读取。

word64 length;
word32 h, l;

inFile.GetWord32(h, BIG_ENDIAN_ORDER);
inFile.GetWord32(l, BIG_ENDIAN_ORDER);

length = ((word64)h << 32) | l;

这是用于此示例的数据文件。

$ hexdump -C test.dat
00000000 00 00 00 00 00 00 00 5e 08 07 06 05 08 07 06 05 |.......^........|
00000010 08 07 06 05 08 07 06 05 b0 82 79 ee a6 d8 8a 0e |..........y.....|
00000020 a6 b3 a4 7e 63 bd 9a bc 0e e4 b6 be 3e eb 36 64 |...~c.......>.6d|
00000030 72 cd ba 91 8d e0 d3 c5 cd 64 ae c0 51 de a7 c9 |r........d..Q...|
00000040 1e a8 81 6d c0 d5 42 2a 17 5a 19 62 1e 9c ab fd |...m..B*.Z.b....|
00000050 21 3d b0 8f e2 b3 7a d4 08 8d ec 00 e0 1e 5e 78 |!=....z.......^x|
00000060 56 6d f5 3e 8c 5f fe 54 |Vm.>._.T|

关于c++ - 流转换过滤器 : invalid PKCS #7 block padding found using AES decryption,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56945847/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com