Como fazer a criptografia usando o AES no Openssl

Eu estou tentando escrever um programa de exemplo para fazer a criptografia AES usando Openssl. Eu tentei passar pela documentação do Openssl (é uma dor), não consegui descobrir muito. Eu fui através do código e encontrei a API usando o que eu escrevi um pequeno programa como abaixo (por favor, omita os números de linha). Eu não vejo nenhuma criptografia acontecendo … estou faltando alguma coisa?

PS: Eu não recebo nenhum erro na compilation.

1 #include  2 #include  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 me ajude a descobrir isso …

Confira este link que tem um código de exemplo para criptografar / descriptografar dados usando AES256CBC usando a API EVP.

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

Além disso, você pode verificar o uso de AES256 CBC em um projeto de código aberto detalhado desenvolvido por mim em https://github.com/llubu/mpro

O código é detalhado o suficiente com comentários e se você ainda precisar de muita explicação sobre a própria API eu sugiro conferir este livro Network Security with OpenSSL por Viega / Messier / Chandra (google ele você encontrará facilmente um pdf deste ..) Leia o capítulo 6 que é específico para cifras simétricas usando a API EVP. Isso me ajudou muito a entender as razões por trás do uso de várias funções e estruturas do EVP.

e se você quiser mergulhar fundo na biblioteca de criptografia Openssl, sugiro baixar o código do site openssl (a versão instalada em sua máquina) e, em seguida, examine a implementação da implementação de EVP e aeh api.

Mais uma sugestão do código que você postou acima eu vejo que você está usando a API de aes.h em vez disso use EVP. Verifique a razão para fazer isso aqui OpenSSL usando EVP vs algoritmo API para criptografia simétrica bem explicado por Daniel em um dos pergunta feita por mim ..

Eu estou tentando escrever um programa de exemplo para fazer a criptografia AES usando Openssl.

Essa resposta é muito popular, então vou oferecer algo mais atualizado, já que o OpenSSL adicionou alguns modos de operação que provavelmente irão ajudá-lo.

Primeiro, não use AES_encrypt e AES_decrypt . Eles são de baixo nível e mais difíceis de usar. Além disso, é uma rotina somente de software e nunca usará aceleração de hardware, como o AES-NI. Finalmente, está sujeito a questões de endianess em algumas plataformas obscuras.

Em vez disso, use as interfaces EVP_* . As funções EVP_* usam aceleração de hardware, como AES-NI, se disponível. E não sofre problemas de endianess em plataformas obscuras.

Segundo, você pode usar um modo como o CBC, mas o texto cifrado não terá garantias de integridade e autenticidade. Então você geralmente quer um modo como o EAX, o CCM ou o GCM. (Ou você manualmente tem que aplicar um HMAC após a criptografia em uma chave separada.)

Terceiro, o OpenSSL tem uma página wiki que provavelmente lhe interessará: Criptografia e Descriptografia Autenticadas por EVP . Ele usa o modo GCM.

Finalmente, aqui está o programa para criptografar usando o AES / GCM. O exemplo do wiki OpenSSL é baseado nele.

 #include  #include  #include  #include  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; } } 

Eu não sei o que está errado com o seu, mas uma coisa é certa é que você precisa chamar AES_set_decrypt_key() antes de descriptografar a mensagem. Também não tente imprimir como% s porque a mensagem criptografada não é mais composta por caracteres ascii. Por exemplo:

 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: sua chave é 192 bits, não é isso …

Minha sugestão é correr

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

no debugger e veja o que exatamente está fazendo. openssl.c é o único tutorial / guia de referência / introdução real que o OpenSSL tem. Toda a outra documentação é apenas uma referência da API.

U1: Meu palpite é que você não está definindo algumas outras opções necessárias, como o modo de operação (preenchimento).

U2: esta é provavelmente uma duplicata desta questão: AES CTR 256 Encryption Modo de operação no OpenSSL e respostas provavelmente ajudarão.

    Intereting Posts