I am having some trouble decrypting a string correctly. What is infuriating about it is that it is only the first few bytes that are messed up, the remaining characters are correct.
So I had my test program working fine when I was just using a hard coded IV for encrypting and decrypting. The program takes a String, encrypts it (using AES), and then I get a hex representation of the encrypted binary. The problem arose when I tried to append the IV onto the end of the cipher text. Peculiarly, the length of the hex String did not increase after appending the IV. But, the decryption function seems to be obtaining the IV from the end of the cipher text, otherwise it wouldn't be able to decrypt any of it, right?
I have tried a bunch of different things, like creating a buffer of the exact size it needs to be, and adding the cipher text and IV using memcpy
. Here is the code:
AES Encryption
int encryptAes(const char *plainText, char *cipherText, const char *key) {
unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
int plainTextLength = strlen(plainText);
int cipherTextLength = 0;
int blockLength = 0;
static const int MAX_PADDING_LENGTH = 16;
EVP_CIPHER_CTX encryptCtx;
EVP_CIPHER_CTX_init(&encryptCtx);
EVP_EncryptInit_ex(&encryptCtx, EVP_aes_256_cbc(), NULL, key, iv);
if (!EVP_EncryptUpdate(&encryptCtx, cipherText, &blockLength, (unsigned char *) plainText, plainTextLength) ) {
printf("Error in EVP_EncryptUpdate \n");
return 1;
}
cipherTextLength += blockLength;
if (!EVP_EncryptFinal_ex(&encryptCtx, cipherText + cipherTextLength, &blockLength)) {
printf("Error in EVP_EncryptFinal_ex \n");
return 1;
}
cipherTextLength += blockLength;
// Append the IV
memcpy(cipherText + cipherTextLength, iv, 16);
EVP_CIPHER_CTX_cleanup(&encryptCtx);
return cipherTextLength;
}
AES Decryption
int decryptAes(const char *cipherText, char *decipheredPlainText, const size_t cipherTextLength, const char *key) {
// unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
unsigned char iv[16];
memcpy(iv, cipherText + cipherTextLength, 16);
int plainTextLength = 0;
int blockLength = 0;
EVP_CIPHER_CTX decryptCtx;
EVP_CIPHER_CTX_init(&decryptCtx);
EVP_DecryptInit_ex(&decryptCtx, EVP_aes_256_cbc(), NULL, key, iv);
if (!EVP_DecryptUpdate(&decryptCtx, decipheredPlainText, &blockLength, cipherText, cipherTextLength)) {
printf("Error in EVP_DecryptUpdate\n");
return 1;
}
plainTextLength += blockLength;
if (!EVP_DecryptFinal_ex(&decryptCtx, decipheredPlainText + plainTextLength, &blockLength)) {
printf("Error in EVP_DecryptFinal_ex\n");
return 1;
}
plainTextLength += blockLength;
decipheredPlainText[plainTextLength] = '\0';
EVP_CIPHER_CTX_cleanup(&decryptCtx);
return plainTextLength;
}
This produces the output:
Original Plain Text [cipher cipher cipher cipher CIPHER TEXT! 187? 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y]
Hexadecimal is [be1c1aaa5827be124023a96a3360da922c244acd845e8914d03cfac69d312948e10f8ef7a99a64acbc6996724315f6cb0bf441ba3b08ab25cae64389f6ded77b1579e847d3e18ca89e71a3c4ec5ca4e3089b7bc2e6bc9ef8d175406bf4b53005a91e285d117e5990176d85793bd75853]
Decrypted Plain Text [�}kaw&d��~C�Rmfpher cipher CIPHER TEXT! 187? 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y]
If I remove the line memcpy(cipherText + cipherTextLength, iv, 16);
from the encryption function, and uncomment the hardcoded IV at the beginning of the decryption function (and comment the following two lines), the output is correct:
Original Plain Text [cipher cipher cipher cipher CIPHER TEXT! 187? 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y]
Hexadecimal is [be1c1aaa5827be124023a96a3360da922c244acd845e8914d03cfac69d312948e10f8ef7a99a64acbc6996724315f6cb0bf441ba3b08ab25cae64389f6ded77b1579e847d3e18ca89e71a3c4ec5ca4e3089b7bc2e6bc9ef8d175406bf4b53005a91e285d117e5990176d85793bd75853]
Decrypted Plain Text [cipher cipher cipher cipher CIPHER TEXT! 187? 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y]
Note!, the hexadecimal is the same in both cases.
Can anyone see where I'm going wrong here. I encountered something similar to this before, but can't seem to remember how I got around it. Obviously there is something afoot when trying to append the IV. There is ample space in cipherText
to accommodate the addition of the IV.
Thanks in advance.