Reputation: 2338
I have this code that I found on SO and it works. My problem is that encryption and decryption are in the same file. Naturally, I want to separate them into two functions. The problem is the decoder needs the original input length. Isn't it a security vulnerability? How can I decrpyt without knowing the original length of the input?
/* computes the ciphertext from plaintext and key using AES256-CBC algorithm */
string cipher_AES(string key, string message)
{
size_t inputslength = message.length();
unsigned char aes_input[inputslength];
unsigned char aes_key[AES_KEYLENGTH];
memset(aes_input, 0, inputslength/8);
memset(aes_key, 0, AES_KEYLENGTH/8);
strcpy((char*) aes_input, message.c_str());
strcpy((char*) aes_key, key.c_str());
/* init vector */
unsigned char iv[AES_BLOCK_SIZE];
memset(iv, 0x00, AES_BLOCK_SIZE);
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, AES_KEYLENGTH, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, AES_KEYLENGTH, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv, AES_DECRYPT);
stringstream ss;
for(int i = 0; i < encslength; i++)
{
ss << enc_out[i];
}
return ss.str(););
}
Upvotes: 1
Views: 1393
Reputation: 85256
First of all, AES encryption takes place 1-to-1 in blocks of 128 bits, so you already know the message size with a 16-byte accuracy by just looking at the ciphertext.
Then, for the last block you just need to determine where the message ends. The standard solution for that is to use padding (e.g. PKCS#7). Or just store the message length at the beginning and encrypt it together with the message.
You can of course continue using OpenSSL AES API, and implement padding or some other mechanism yourself. But OpenSSL already has higher-level API (EVP), which does AES, CBC and PKCS padding automatically.
See EVP Symmetric Encryption and Decryption official OpenSSL wiki page for an example of using the EVP API.
Unrelated notes:
a fixed IV (especially zero IV) is insecure. Consider generating a random IV and storing it together with the ciphertext (e.g. using RAND_bytes).
check out also AES GCM mode for authenticated encryption (encryption + secure checksum), this way the encrypted message additionally becomes tamper-proof. See this example.
Upvotes: 3