Crypto++:在 Python 中加密,在 C++ 中解密

3 投票
1 回答
2259 浏览
提问于 2025-04-19 15:14

我正在尝试做以下事情:在一个Python脚本中,我使用pycrypto库来加密一些文本。然后我把它保存到文件里。接着,我加载这个文件,并使用在Python中用的同一个密钥来解码加密的文本。但是在执行stfDecryptor.MessageEnd();时出错,错误信息是:

"CryptoCPP::InvalidCiphertext at memory location [某个内存地址]"

这是我的代码:

Python:

from Crypto.Cipher import AES
BLOCK_SIZE = 16
PADDING = '{'

# one-liner to sufficiently pad the text to be encrypted
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: c.encrypt(pad(s))
secret = 'MyKey123456789ab' 

# create a cipher object using the random secret
cipher = AES.new(secret)

# encode a string
encoded = EncodeAES(cipher, textIn)

#save to file
fileOut = open("enc_shader.vert","w")
fileOut.write(encoded)
fileOut.close()

CPP :

 std::string key = "MyKey123456789ab";
 std::string iv = "aaaaaaaaaaaaaaaa";

 std::ifstream fileIn("enc_shader.vert");

std::stringstream buffer;
buffer << fileIn.rdbuf();
std::string ciphertext1 = buffer.str();
CryptoPP::AES::Decryption aesDecryption((byte*)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, (byte*)iv.c_str() );

CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
stfDecryptor.Put( reinterpret_cast<const unsigned char*>( ciphertext1.c_str() ), ciphertext1.size() );
stfDecryptor.MessageEnd();//fails here.

根据我所了解,这两个端点应该可以正常工作,因为pycrypto只是CryptoCPP库的一个封装。也许我在CPP那边漏掉了填充的步骤?

更新:

好的,我发现更改填充方案:

 CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) ,BlockPaddingSchemeDef::NO_PADDING);

可以在CPP那边解码字符串。但是解码后的字符串包含了填充字符。比如说,如果原始字符串是"aaaaaaaaaaaaaaaaa"

解码后的字符串看起来像这样:

"aaaaaaaaaaaaaaaaa{{{{{{{{{{{{{{{"

这里添加了15个字节来填充到32个字节。

为什么Crypto++在解密时不去掉这些填充字符呢?

1 个回答

3

你的Python加密代码是手动添加'{'字符来填充到块大小。这种填充方式并不是标准的填充模式,所以Crypto++的代码无法通过内置的填充方案来去掉这些填充字符。换句话说,你应该使用NO_PADDING来解密,然后自己去掉填充。

不过,最好是让Python代码使用PKCS#7填充,这样你就可以在Crypto++中使用PKCS_PADDING作为选项。

撰写回答