I am trying to encrypt a byte array that has been parsed to a string. This seems to work for all cases, except for the case that the byte array contains 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, 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;
}
In this case, the byte array contains 0x00. This causes the cipherText to be cut short leading to an invalid length. An exception is thrown stating: 'StreamTransformationFilter: invalid PKCS #7 block padding found'
So I thought it would be better to use an ArraySource and ArraySink to be sure that a string is not zero terminated.
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;
}
In this case, an exception is thrown that the ciphertext is not a multiple of the key length, which clearly is not the case here. (Key = 16 bytes, Ciphertext = 16 bytes). I think that the library casts the byte array to a string leaving out all the data after the 0x00 byte.
What am I doing wrong?
sizemember function is always used. Your problem lies elsewhere.plainTextto the actual size of the recovered message before you performreturn plainText. You probably need to callArraySinkmember functionTotalPutLengthto get the recovered message size. An example is available at ArraySink on the Crypto++ wiki.