ECB, CFB, OFB in Openssl

I know that when I use CBC mode using Openssl, I can specify as input which is a multiple of the size of the block. But what about other modes? ECB, CFB, OFB? I saw a doc , but this is not all clear to me. Should I call them in a loop?

Let's say the ECB. It encrypts 64 bits at a time. So, will the pseudo code look like this (should it 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 does not work well. When I change c += 8; on c += 16; then this is normal. What is a good way to do this? I mean that we all know that 8x8 = 64 bits, so this should be correct, but it is not, encryption / decryption only works when I have c += 16; .

What about other encryption modes?

An example for ECB mode (note that the question also applies to other modes;)):

 #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 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; } 
+4
source share
1 answer

Let's say the ECB. It encrypts 64 bits at a time

AES is a 128-bit block cipher. It encrypts / decrypts 128-bit at a time. This is the standard. The AES_encrypt / AES_decrypt block expects 128 bits or 16 bytes of input and output data lengths.

But with the above code, it does not work well. When I change from + = 8; in c + = 16; this is normal. What is a good way to do this? I mean that we all know that 8x8 = 64 bits, so this should be correct, but it is not, encryption / decryption only works when I have c + = 16;

That's why it works great on

c + = 16

In addition, there are several problems in your code.

 unsigned char enc_out[encslength]; 

Please save the dec_out size from encslength, since you are decrypting the encslength bytes, not the lengthlength 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 by 128 block ciphers.

 long c = 0; while(c < encslength) { AES_ecb_encrypt(paddedinput+c, enc_out+c, &enc_key, AES_ENCRYPT); c += 16; } 

A 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:

  • CFB mode No need to fill in data. Use AES_cfb128_encrypt and the initialization vector (IV) along with the key.

For encryption:

 AES_cfb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, AES_ENCRYPT); 

To decrypt:

 AES_cfb128_decrypt (enc_out, dec_out, inputlength, &enc_key, iv, AES_ENCRYPT); 
  • OFB mode Similarly, in OFB mode there is no need to enter data. Use AES_ofb128_encrypt and IV along with the key.

For encryption:

 //Initialize num to 0. num = 0; AES_ofb128_encrypt (paddedinput, enc_out, inputlength, &enc_key, iv, &num); 

To decrypt:

 num = 0; AES_ofb128_encrypt (enc_out, dec_out, inputlength, &enc_key, iv, &num); 

You may need to modify the code a bit to suit your needs.

Learn more about block encryption mode .

+3
source

Source: https://habr.com/ru/post/1497594/


All Articles