Reputation: 813
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?
Upvotes: 0
Views: 2255
Reputation: 112865
Encryption is a binary byte not a character operation. As such the encrypted output can not be cast to a string. If you need a string output encode the encrypted data to a string compatible format common formats are Base64 and hexadecimal.
In particular a null byte in a character string by convention in "C" like signals languages the end of the string.
That is on encryption encode the binary data to a string format and on decryption first decode the string representation to binary data by using the inverse of the encoding operation.
Upvotes: 1