aes256 - Encriptación/descifrado AES(aes-cbc-128, aes-cbc-192, aes-cbc-256) con openssl C
openssl aes256 (2)
Solo quiero probar AES desde openSSL con estos 3 modos: con 128,192 y 256 teclas de longitud, pero mi texto descifrado es diferente de mi entrada y no sé por qué. Además, cuando paso una gran longitud de entradas (digamos 1024 bytes), mi programa muestra el core dumped
... Mi entrada es siempre la misma pero no importa, al menos por ahora. Aquí está el código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
int main(int argc, char **argv)
{
int i;
int keylength;
printf("Give a key length [only 128 or 192 or 256!]:/n");
scanf("%d", &keylength);
/* generate a key with a given length */
unsigned char aes_key[keylength];
memset(aes_key, 0, sizeof(aes_key));
if (!RAND_bytes(aes_key, keylength))
{
exit(-1);
}
aes_key[keylength-1] = ''/0'';
int inputslength;
printf("Give an input''s length:/n");
scanf("%d", &inputslength);
/* generate input with a given length */
unsigned char aes_input[inputslength+1];
memset(aes_input, ''0'', sizeof(aes_input));
aes_input[inputslength] = ''/0'';
/*printf("original:/t");
for(i=0; i<inputslength; i++)
{
printf("%c ", aes_input[i]);
}
printf("/n");*/
/* init vector */
unsigned char iv[AES_BLOCK_SIZE];
if (!RAND_bytes(iv, AES_BLOCK_SIZE))
{
exit(-1);
}
//printf("AES_BLOCK_SIZE = %d/n", AES_BLOCK_SIZE); // aes block size is 16 bytes = 128 bits
AES_KEY enc_key, dec_key;
unsigned char enc_out[AES_BLOCK_SIZE];
unsigned char dec_out[AES_BLOCK_SIZE];
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_decrypt(enc_out, dec_out, &dec_key);
printf("original:/t");
for(i=0;*(aes_input+i)!=0x00;i++)
printf("%X ",*(aes_input+i));
printf("/nencrypted:/t");
for(i=0;*(enc_out+i)!=0x00;i++)
printf("%X ",*(enc_out+i));
printf("/ndecrypted:/t");
for(i=0;*(dec_out+i)!=0x00;i++)
printf("%X ",*(dec_out+i));
printf("/n");
/*printf("/n/noriginal:/t");
for(i=0; i<inputslength; i++)
{
printf("%x ", dec_out[i]);
}
printf("/n");*/
return 0;
}
EDITAR:
Cuando cambié el tamaño de las salidas a la inputslength
de inputslength
lugar de AES_BLOCK_SIZE
obtuve resultados:
Give a key length [only 128 or 192 or 256!]:
128
Give an input''s length:
5
original: 30 30 30 30 30
encrypted: 94 56 50 7E 19 B2 1C CE 20 23 4A E7 10 AF DB E3 30 30 30 30 30
decrypted: E1 5F F4 3D E8 8D 91 19 CD 3E 22 1E AF 1C 8F 5A 94 56 50 7E 19 B2 1C CE 20 23 4A E7 10 AF DB E3 30 30 30 30 30
Entonces, ¿es posible que exista un problema con los tamaños de los outpus y el tamaño del iv? ¿Qué tamaños deben tener (para AES-CBC-128, AES-CBC-192, AES-CBC-256)?
@WhozCraig: ¡Muchas gracias por la ayuda! ¡Me explicó mucho! Pero hay un problema más. Cambié arrays estáticos en dinámicos. Cuando lo hice, ocurrieron algunos erros. Pero solo se producen cuando doy un tamaño de entrada enorme, eche un vistazo a la salida de valgrind: http://pastie.org/private/bzofrrtgrlzr0doyb3g . El error ocurre solo cuando paso una entrada enorme, cuando paso un tamaño pequeño (como en su ejemplo, 10) está bien. Todo lo demás está funcionando perfectamente.
#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)
{
size_t inputslength = 0;
printf("Give an input''s length:/n");
scanf("%lu", &inputslength);
int keylength;
printf("Give a key length [only 128 or 192 or 256!]:/n");
scanf("%d", &keylength);
// generate a key with a given length
unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8));
memset(aes_key, 0, keylength/8);
RAND_bytes(aes_key, keylength/8);
// generate input with a given length
unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
memset(aes_input, ''X'', sizeof(aes_input));
// init vectors
unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
unsigned char *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
// iv_dec == iv_enc
RAND_bytes(iv_enc, AES_BLOCK_SIZE);
memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
// buffers for encryption and decryption
const size_t length = (((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) * (length));
unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_KEY encKey, decKey;
AES_set_encrypt_key(aes_key, keylength, &encKey);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &encKey, iv_enc, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &decKey);
AES_cbc_encrypt(enc_out, dec_out, length, &decKey, iv_dec, AES_DECRYPT);
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));
free(aes_key);
aes_key = NULL;
free(aes_input);
aes_input = NULL;
free(iv_enc);
iv_enc = NULL;
free(iv_dec);
iv_dec = NULL;
free(enc_out);
enc_out = NULL;
free(dec_out);
dec_out = NULL;
return 0;
}
EDITAR:
Ok, algo andaba mal con el código anterior que publiqué, aquí hay uno nuevo, que funciona perfectamente, incluso para entradas enormes. Saludos una vez más por ayudarme! :)
#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;
printf("Give a key length [only 128 or 192 or 256!]:/n");
scanf("%d", &keylength);
/* generate a key with a given length */
unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (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 = (unsigned char*)malloc(sizeof(unsigned char) *inputslength);
memset(aes_input, ''X'', inputslength);
/* init vector */
unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE), *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE);
RAND_bytes(iv_enc, AES_BLOCK_SIZE);
memcpy(iv_dec, iv_enc, 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 = (unsigned char*)malloc(sizeof(unsigned char) *encslength);
unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) *inputslength);
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
printf("original:/t");
hex_print(aes_input, inputslength);
printf("encrypt:/t");
hex_print(enc_out, encslength);
printf("decrypt:/t");
hex_print(dec_out, inputslength);
// free memory here
return 0;
}
Eche un vistazo a esta versión modificada de su código. Tenga en cuenta lo siguiente:
- Añadido hex_print (menor)
- Se ha agregado el tamaño adecuado del búfer clave (medio)
- Se agregó el tamaño adecuado del búfer de cifrado de salida (que debe ser un múltiplo de tamaño de bloque, y si el búfer de origen original es un múltiplo de tamaño de bloque exacto, todavía necesita un bloque completo de relleno (consulte el apartado PKCS 5 padding para más información).
- Mismo IV usado tanto para encriptar como para desencriptar.
- Finalmente, por extraño que parezca, se
AES_cbc_encrypt()
tanto para el cifrado como para el descifrado (consulte el último parámetro de la llamada).
Código fuente
#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;
printf("Give a key length [only 128 or 192 or 256!]:/n");
scanf("%d", &keylength);
/* generate a key with a given length */
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);
/* init vector */
unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE];
RAND_bytes(iv_enc, AES_BLOCK_SIZE);
memcpy(iv_dec, iv_enc, 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));
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
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;
}
Salida de prueba
Give a key length [only 128 or 192 or 256!]:
128
Give an input''s length:
10
original: 58 58 58 58 58 58 58 58 58 58
encrypt: A9 66 C5 24 A4 02 AB 96 08 65 F7 22 A5 FB BE 26
decrypt: 58 58 58 58 58 58 58 58 58 58
Segunda salida de prueba
Give a key length [only 128 or 192 or 256!]:
128
Give an input''s length:
10
original: 58 58 58 58 58 58 58 58 58 58
encrypt: C2 47 6D B1 A1 68 29 53 55 74 C5 CC 3F 27 0A 3F
decrypt: 58 58 58 58 58 58 58 58 58 58
Sinceramente espero que esto ayude.