encriptar descifrar con c openssl aes

descifrar - encriptar con openssl



Cómo hacer encriptación usando AES en Openssl (4)

Estoy intentando escribir un programa de ejemplo para hacer el cifrado AES usando Openssl. Intenté revisar la documentación de Openssl (es un dolor), no pude entender mucho. Revisé el código y encontré las API con las que escribí un pequeño programa como el siguiente (omita los números de línea). No veo ninguna encriptación ... ¿Me falta algo?

PD: No obtengo ningún error en la compilación.

1 #include <stdio.h> 2 #include <openssl/aes.h> 3 4 static const unsigned char key[] = { 5 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 6 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 7 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 8 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 9 }; 10 11 void main() 12 { 13 unsigned char text[]="virident"; 14 unsigned char out[10]; 15 unsigned char decout[10]; 16 17 AES_KEY wctx; 18 19 AES_set_encrypt_key(key, 128, &wctx); 20 AES_encrypt(text, out, &wctx); 21 22 printf("encryp data = %s/n", out); 23 24 AES_decrypt(out, decout, &wctx); 25 printf(" Decrypted o/p: %s /n", decout); 26 27 28 }

Por favor, ayúdame a resolver esto ...


Estoy intentando escribir un programa de ejemplo para hacer el cifrado AES usando Openssl.

Esta respuesta es bastante popular, así que voy a ofrecer algo más actualizado ya que OpenSSL agregó algunos modos de operación que probablemente te ayuden.

Primero, no use AES_encrypt y AES_decrypt . Son de bajo nivel y más difíciles de usar. Además, es una rutina de solo software, y nunca usará aceleración de hardware, como AES-NI. Finalmente, está sujeto a problemas de endianess en algunas plataformas oscuras.

En su lugar, use las interfaces EVP_* . Las funciones EVP_* usan aceleración de hardware, como AES-NI, si está disponible. Y no sufre problemas de endianess en plataformas oscuras.

En segundo lugar, puede usar un modo como CBC, pero el texto cifrado carecerá de integridad y garantías de autenticidad. Por lo tanto, generalmente quiere un modo como EAX, CCM o GCM. (O debe aplicar manualmente un HMAC después del cifrado con una clave diferente).

En tercer lugar, OpenSSL tiene una página wiki que probablemente le interese: EVP Authenticated Encryption and Decryption . Utiliza el modo GCM.

Finalmente, aquí está el programa para encriptar usando AES / GCM. El ejemplo de wiki de OpenSSL se basa en él.

#include <openssl/evp.h> #include <openssl/aes.h> #include <openssl/err.h> #include <string.h> int main(int arc, char *argv[]) { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* Set up the key and iv. Do I need to say to not hard code these in a real application? :-) */ /* A 256 bit key */ static const unsigned char key[] = "01234567890123456789012345678901"; /* A 128 bit IV */ static const unsigned char iv[] = "0123456789012345"; /* Message to be encrypted */ unsigned char plaintext[] = "The quick brown fox jumps over the lazy dog"; /* Some additional data to be authenticated */ static const unsigned char aad[] = "Some AAD data"; /* Buffer for ciphertext. Ensure the buffer is long enough for the * ciphertext which may be longer than the plaintext, dependant on the * algorithm and mode */ unsigned char ciphertext[128]; /* Buffer for the decrypted text */ unsigned char decryptedtext[128]; /* Buffer for the tag */ unsigned char tag[16]; int decryptedtext_len = 0, ciphertext_len = 0; /* Encrypt the plaintext */ ciphertext_len = encrypt(plaintext, strlen(plaintext), aad, strlen(aad), key, iv, ciphertext, tag); /* Do something useful with the ciphertext here */ printf("Ciphertext is:/n"); BIO_dump_fp(stdout, ciphertext, ciphertext_len); printf("Tag is:/n"); BIO_dump_fp(stdout, tag, 14); /* Mess with stuff */ /* ciphertext[0] ^= 1; */ /* tag[0] ^= 1; */ /* Decrypt the ciphertext */ decryptedtext_len = decrypt(ciphertext, ciphertext_len, aad, strlen(aad), tag, key, iv, decryptedtext); if(decryptedtext_len < 0) { /* Verify error */ printf("Decrypted text failed to verify/n"); } else { /* Add a NULL terminator. We are expecting printable text */ decryptedtext[decryptedtext_len] = ''/0''; /* Show the decrypted text */ printf("Decrypted text is:/n"); printf("%s/n", decryptedtext); } /* Remove error strings */ ERR_free_strings(); return 0; } void handleErrors(void) { unsigned long errCode; printf("An error occurred/n"); while(errCode = ERR_get_error()) { char *err = ERR_error_string(errCode, NULL); printf("%s/n", err); } abort(); } int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad, int aad_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext, unsigned char *tag) { EVP_CIPHER_CTX *ctx = NULL; int len = 0, ciphertext_len = 0; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the encryption operation. */ if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) handleErrors(); /* Set IV length if default 12 bytes (96 bits) is not appropriate */ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors(); /* Initialise key and IV */ if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ if(aad && aad_len > 0) { if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); } /* Provide the message to be encrypted, and obtain the encrypted output. * EVP_EncryptUpdate can be called multiple times if necessary */ if(plaintext) { if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) handleErrors(); ciphertext_len = len; } /* Finalise the encryption. Normally ciphertext bytes may be written at * this stage, but this does not occur in GCM mode */ if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); ciphertext_len += len; /* Get the tag */ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) handleErrors(); /* Clean up */ EVP_CIPHER_CTX_free(ctx); return ciphertext_len; } int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx = NULL; int len = 0, plaintext_len = 0, ret; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the decryption operation. */ if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) handleErrors(); /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors(); /* Initialise key and IV */ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ if(aad && aad_len > 0) { if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); } /* Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if(ciphertext) { if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) handleErrors(); plaintext_len = len; } /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) handleErrors(); /* Finalise the decryption. A positive return value indicates success, * anything else is a failure - the plaintext is not trustworthy. */ ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); /* Clean up */ EVP_CIPHER_CTX_free(ctx); if(ret > 0) { /* Success */ plaintext_len += len; return plaintext_len; } else { /* Verify failed */ return -1; } }


Echa un vistazo a este enlace que tiene un código de ejemplo para encriptar / descifrar datos usando AES256CBC usando EVP API.

https://github.com/saju/misc/blob/master/misc/openssl_aes.c

También puede verificar el uso de AES256 CBC en un proyecto detallado de código abierto desarrollado por mí en https://github.com/llubu/mpro

El código es lo suficientemente detallado con comentarios y si aún necesita mucha explicación sobre la API, le sugiero que consulte este libro Seguridad de red con OpenSSL de Viega / Messier / Chandra (en Google encontrará fácilmente un pdf de esto ...) lea el capítulo 6 que es específico para cifrados simétricos que usan EVP API. Esto me ayudó mucho a entender las razones detrás de usar varias funciones y estructuras de EVP.

y si desea profundizar en la biblioteca de criptografía Openssl, le sugiero que descargue el código del sitio web de openssl (la versión instalada en su máquina) y luego busque la implementación de EVP y aeh api.

Una sugerencia más del código que publiqué anteriormente, veo que estás usando la API de aes.h, en cambio, usa EVP. Comprueba la razón para hacerlo aquí. OpenSSL usa la API de EVP vs. Algoritmo simétrico, muy bien explicada por Daniel en una de las pregunta hecha por mí ..


Mi sugerencia es correr

openssl enc -aes-256-cbc -in plain.txt -out encrypted.bin

bajo depuración y ver qué es exactamente lo que está haciendo. openssl.c es la única guía / guía de inicio / referencia real que tiene OpenSSL. Toda la demás documentación es solo una referencia API.

U1: supongo que no está configurando otras opciones necesarias, como el modo de operación (relleno).

U2: probablemente sea un duplicado de esta pregunta: el modo de cifrado AES CTR 256 Encryption en OpenSSL y las respuestas probablemente ayuden.


No sé qué le pasa a los suyos, pero una cosa es segura: debe llamar a AES_set_decrypt_key() antes de descifrar el mensaje. Tampoco intente imprimir como% s porque el mensaje cifrado ya no está compuesto por caracteres ascii. Por ejemplo:

static const unsigned char key[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; int main() { unsigned char text[]="hello world!"; unsigned char enc_out[80]; unsigned char dec_out[80]; AES_KEY enc_key, dec_key; AES_set_encrypt_key(key, 128, &enc_key); AES_encrypt(text, enc_out, &enc_key); AES_set_decrypt_key(key,128,&dec_key); AES_decrypt(enc_out, dec_out, &dec_key); int i; printf("original:/t"); for(i=0;*(text+i)!=0x00;i++) printf("%X ",*(text+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"); return 0; }

U1: tu clave es 192 bit ¿no? ...