C++ 使用CryptoPP库加密和解密字节数组/向量
我试图加密已解析为字符串的字节数组。这似乎适用于所有情况,但字节数组包含0x00的情况除外C++ 使用CryptoPP库加密和解密字节数组/向量,c++,encryption,aes,crypto++,C++,Encryption,Aes,Crypto++,我试图加密已解析为字符串的字节数组。这似乎适用于所有情况,但字节数组包含0x00的情况除外 int main() { byte cipherTextWithZeroByte[32] = { 0xD3, 0xFA, 0xD6, 0xEC, 0x84, 0x4E, 0xD3, 0xD8, 0x2B, 0x76, 0x6C, 0xE8, 0x02, 0xF2, 0xB2, 0x6F, 0x00, 0xE8, 0x99, 0x8C, 0xEC, 0
int main()
{
byte cipherTextWithZeroByte[32] = {
0xD3, 0xFA, 0xD6, 0xEC, 0x84, 0x4E, 0xD3, 0xD8,
0x2B, 0x76, 0x6C, 0xE8, 0x02, 0xF2, 0xB2, 0x6F,
0x00, 0xE8, 0x99, 0x8C, 0xEC, 0x4B, 0x3C, 0x7D,
0xAC, 0xDE, 0x86, 0x02, 0x51, 0xAB, 0x3F, 0x04
};
string cipherText((char *)cipherTextWithZeroByte);
string plainText = decrypt(cipherText, sizeof(cipherTextWithZeroByte));
return 1;
}
string decrypt(string cipherText, int size)
{
string decryptedText;
CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(decryptedText)));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(cipherText.c_str()), size);
stfDecryptor.MessageEnd();
return decryptedText;
}
intmain()
{
字节密文带零字节[32]={
0xD3、0xFA、0xD6、0xEC、0x84、0x4E、0xD3、0xD8、,
0x2B、0x76、0x6C、0xE8、0x02、0xF2、0xB2、0x6F、,
0x00、0xE8、0x99、0x8C、0xEC、0x4B、0x3C、0x7D、,
0xAC、0xDE、0x86、0x02、0x51、0xAB、0x3F、0x04
};
字符串密文((char*)带零字节的密文);
字符串明文=解密(密文,sizeof(密文带零字节));
返回1;
}
字符串解密(字符串密文,整数大小)
{
字符串解密文本;
CryptoPP::AES::Decryption AES Decryption(密钥,CryptoPP::AES::默认密钥长度);
CryptoPP::CBC_Mode_ExternalCipher::解密cbcDecryption(AESDryption,iv);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption,
新的CryptoPP::HexEncoder(
新的CryptoPP::StringSink(decryptedText));
stfDecryptor.Put(reinterpret_cast(cipherText.c_str()),size);
stfDecryptor.MessageEnd();
返回解密文本;
}
在本例中,字节数组包含0x00。这会导致密文缩短,导致长度无效。引发异常,声明:“StreamTransformationFilter:无效PKCS#找到7块填充”
因此我认为最好使用ArraySource和ArraySink来确保字符串不是以零结尾的
int main()
{
byte cipherTextWithZeroByte[32] = {
0xD3, 0xFA, 0xD6, 0xEC, 0x84, 0x4E, 0xD3, 0xD8,
0x2B, 0x76, 0x6C, 0xE8, 0x02, 0xF2, 0xB2, 0x6F,
0x00, 0xE8, 0x99, 0x8C, 0xEC, 0x4B, 0x3C, 0x7D,
0xAC, 0xDE, 0x86, 0x02, 0x51, 0xAB, 0x3F, 0x04
};
vector<byte> cipherTextData(cipherTextWithZeroByte, cipherTextWithZeroByte + sizeof(cipherTextWithZeroByte) / sizeof(cipherTextWithZeroByte[0]));
vector<byte> plainTextData = decrypt(cipherTextData);
return 1;
}
vector<byte> decrypt(vector<byte> cipherText)
{
vector<byte> plainText;
plainText.resize(cipherText.size());
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor;
decryptor.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
CryptoPP::ArraySource ss(&cipherText[0], cipherText.size(), true,
new CryptoPP::HexEncoder(
new CryptoPP::StreamTransformationFilter(decryptor,
new CryptoPP::ArraySink(plainText.data(), plainText.size()))));
return plainText;
}
intmain()
{
字节密文带零字节[32]={
0xD3、0xFA、0xD6、0xEC、0x84、0x4E、0xD3、0xD8、,
0x2B、0x76、0x6C、0xE8、0x02、0xF2、0xB2、0x6F、,
0x00、0xE8、0x99、0x8C、0xEC、0x4B、0x3C、0x7D、,
0xAC、0xDE、0x86、0x02、0x51、0xAB、0x3F、0x04
};
向量cipherTextData(cipherTextWithZeroByte,cipherTextWithZeroByte+sizeof(cipherTextWithZeroByte)/sizeof(cipherTextWithZeroByte[0]);
向量明文数据=解密(密文数据);
返回1;
}
矢量解密(矢量密文)
{
矢量明文;
plainText.resize(cipherText.size());
CryptoPP::CBC_模式::解密解密器;
解密器.SetKeyWithIV(key,sizeof(key),iv,sizeof(iv));
CryptoPP::ArraySource ss(&cipherText[0]),cipherText.size(),true,
新的CryptoPP::HexEncoder(
新的CryptoPP::StreamTransformationFilter(解密程序,
新的CryptoPP::ArraySink(plainText.data(),plainText.size());
返回纯文本;
}
在这种情况下,将引发一个异常,即密文不是密钥长度的倍数,这里显然不是这种情况。(密钥=16字节,密文=16字节)。我认为库将字节数组强制转换为一个字符串,而不包含0x00字节之后的所有数据
我做错了什么?加密是一个二进制字节而不是字符操作。因此,加密输出不能转换为字符串。如果需要字符串输出,请将加密数据编码为与字符串兼容的格式。常用格式为Base64和十六进制 特别是,按照“C”类语言的约定,字符串中的空字节表示字符串的结尾
即在加密时,将二进制数据编码为字符串格式,在解密时,首先使用编码操作的逆运算将字符串表示解码为二进制数据 “我认为库将字节数组强制转换为一个字符串,而忽略了0x00字节之后的所有数据…”不,这不会发生。始终使用字符串的
size
成员函数。你的问题在别处。“出现了一个异常,密文不是密钥长度的倍数…”-这里听起来有些不对劲。我不认识这个信息。实际的例外情况是什么?听起来又是一条无效的填充消息(有点)。可能您的文件已过期,需要在更改后重新生成。在第二个示例中,您需要将纯文本
调整为恢复邮件的实际大小,然后再执行返回纯文本
。您可能需要调用ArraySink
成员函数TotalPutLength
,以获取恢复的消息大小。Crypto++wiki上提供了一个示例。