I know that when I use CBC mode with Openssl, I can give as an input which is a multiple of a block size. But how about other modes? ECB, CFB, OFB? I saw a doc but its not all clear to me. Should I call them in a loop?
Lets say, ECB. It encrypts 64 bits at a time. So a pseudocode would look like this (should look like this)?
int len = 512, c = 0;
unsigned char in[len], out[len];
while(c < len)
{
Aes_ecb_encrypt(in+c, out+c, &enckey, AES_ENCRYPT);
c += 8;
}
But with the above code it doesnt encrpyt good. When I change c += 8;
into c += 16;
its ok then. Whats is good way of doing this? I mean, we all know that 8x8 = 64 bits so this should be correct, but it isnt, the encryption/decryption is working only when I have c += 16;
.
What about other cipher modes?
Sample for ECB mode (notice, that the question is also about other modes too;)):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
// a simple hex-print routine. could be modified to print 16 bytes-per-line
static void hex_print(const void* pv, size_t len)
{
const unsigned char * p = (const unsigned char*)pv;
if (NULL == pv)
printf("NULL");
else
{
size_t i = 0;
for (; i<len;++i)
printf("%02X ", *p++);
}
printf("\n");
}
// main entrypoint
int main(int argc, char **argv)
{
int keylength = 256;
unsigned char aes_key[keylength/8];
memset(aes_key, 0, keylength/8);
if (!RAND_bytes(aes_key, keylength/8))
exit(-1);
size_t inputslength = 0;
printf("Give an input's length:\n");
scanf("%lu", &inputslength);
/* generate input with a given length */
unsigned char aes_input[inputslength];
memset(aes_input, 'X', inputslength);
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char paddedinput[encslength];
memset(paddedinput, 0, encslength);
memcpy(paddedinput, aes_input, inputslength);
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, keylength, &enc_key);
long c = 0;
while(c < encslength)
{
AES_ecb_encrypt(paddedinput+c, enc_out+c, &enc_key, AES_ENCRYPT);
c += 8;
}
c = 0;
AES_set_decrypt_key(aes_key, keylength, &dec_key);
while(c < encslength)
{
AES_ecb_encrypt(enc_out+c, dec_out+c, &dec_key, AES_DECRYPT);
c += 8;
}
printf("original:\t");
hex_print(aes_input, sizeof(aes_input));
printf("encrypt:\t");
hex_print(enc_out, sizeof(enc_out));
printf("decrypt:\t");
hex_print(dec_out, sizeof(dec_out));
return 0;
}
Lets say, ECB. It encrypts 64 bits at a time
AES is a 128-bit block cipher. It encrypts/decrypts 128-bit at a time. It is a standard. AES_encrypt/AES_decrypt block expects 128 bits or 16 bytes length of the input and output data.
But with the above code it doesnt encrpyt good. When I change c += 8; into c += 16; its ok then. Whats is good way of doing this? I mean, we all know that 8x8 = 64 bits so this should be correct, but it isnt, the encryption/decryption is working only when I have c += 16;
That is why it is working fine on
c+=16
Apart from this, there are few problems in your code.
unsigned char enc_out[encslength];
Please keep the size of dec_out of encslength since you are decrypting encslength bytes not inputslength in your code.
unsigned char dec_out[encslength];
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, keylength, &enc_key);
In this section, increase c by 16 as AES is 128 block cipher.
long c = 0;
while(c < encslength)
{
AES_ecb_encrypt(paddedinput+c, enc_out+c, &enc_key, AES_ENCRYPT);
c += 16;
}
Similar change here:
c = 0;
AES_set_decrypt_key(aes_key, keylength, &dec_key);
while(c < encslength)
{
AES_ecb_encrypt(enc_out+c, dec_out+c, &dec_key, AES_DECRYPT);
c += 16;
}
About other modes:
For encryption:
AES_cfb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, AES_ENCRYPT);
For decryption:
AES_cfb128_decrypt (enc_out, dec_out, inputlength, &enc_key, iv, AES_ENCRYPT);
For encryption:
//Initialize num to 0.
num = 0;
AES_ofb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, &num);
For decryption:
num = 0;
AES_ofb128_encrypt (enc_out, dec_out, inputlength, &enc_key, iv, &num);
You may need to tweak the code some bit as per your need.
Please read more about block cipher mode of operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With