In message <[EMAIL PROTECTED]> on Mon, 21 Mar 2005 21:06:05 -0300, Rafael Cividanes <[EMAIL PROTECTED]> said:
rafacividanes> I'm doing a little program to encrypt and decrypt rafacividanes> a string using the EVP API. I couldn't understand if I rafacividanes> have to use EVP_DecryptFinal_ex( ) or just rafacividanes> EVP_DecryptUpdate( ) in the decryption operation. The rafacividanes> second function return the entire recovered plaintext, rafacividanes> then I can't understand why EVP_DecryptFinal_ex( ) rafacividanes> exist. Just for checking error? EVP_DecryptFinal_ex() clears the padding that's tucked at the end of the ciphertext, and through the padding, it will also check that the decryption was correctly done. This ALSO applies to messages that are an exact multiple of 8 bytes (or whatever the cipher block size is) in length. rafacividanes> rafacividanes> Here is my code: rafacividanes> rafacividanes> int main(int argc, char *argv[]) rafacividanes> { rafacividanes> EVP_CIPHER_CTX ctx; rafacividanes> char key[EVP_MAX_KEY_LENGTH]; rafacividanes> char iv[EVP_MAX_IV_LENGTH]; rafacividanes> char intext[] = "The problem will be solved until12345"; //32 rafacividanes> rafacividanes> unsigned char outbuf[1024]; rafacividanes> unsigned char recover_msg[1024]; rafacividanes> unsigned char final[1024]; rafacividanes> int size_recover_msg, size_final; rafacividanes> int outlen, tmplen; rafacividanes> int i; rafacividanes> rafacividanes> printf("\n START!!! \n"); rafacividanes> RAND_screen(); rafacividanes> RAND_bytes(key, EVP_MAX_KEY_LENGTH); rafacividanes> RAND_bytes (iv, EVP_MAX_IV_LENGTH); rafacividanes> rafacividanes> //initialization rafacividanes> for (i=0; i<1024; i++){ rafacividanes> outbuf[i]='\0'; rafacividanes> recover_msg[i]='\0'; rafacividanes> final[i]='\0'; rafacividanes> } rafacividanes> rafacividanes> //encryption rafacividanes> EVP_CIPHER_CTX_init(&ctx); rafacividanes> EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc( ), NULL, key, iv); rafacividanes> rafacividanes> printf("\n EVP_CIPHER_CTX_key_length(&ctx): %d ", rafacividanes> EVP_CIPHER_CTX_key_length(&ctx)); rafacividanes> printf("\n Size of plaintext: %d \n", strlen(intext)); rafacividanes> rafacividanes> if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, rafacividanes> strlen(intext))) rafacividanes> printf("\n ERROR! \n"); rafacividanes> rafacividanes> // Buffer passed to EVP_EncryptFinal() must be after data just rafacividanes> // encrypted to avoid overwriting it. rafacividanes> rafacividanes> if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, rafacividanes> &tmplen)) rafacividanes> printf("\n ERROR!! \n"); rafacividanes> rafacividanes> outlen += tmplen; rafacividanes> rafacividanes> //print the ciphertext rafacividanes> printf("\n ciphertext: \n"); rafacividanes> for (i=0;i<outlen;i++) printf("%02x",outbuf[i]); rafacividanes> printf("\n"); rafacividanes> rafacividanes> EVP_CIPHER_CTX_cleanup(&ctx); rafacividanes> rafacividanes> //Decryption rafacividanes> if (!EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc( ), NULL, key, iv)) rafacividanes> printf("\n ERROR!! \n"); rafacividanes> rafacividanes> if (!EVP_DecryptUpdate(&ctx, recover_msg, &size_recover_msg, rafacividanes> outbuf, outlen)) rafacividanes> printf("\n ERROR!! \n"); rafacividanes> rafacividanes> if (!EVP_DecryptFinal_ex(&ctx, final, &size_final)) rafacividanes> printf("\n ERROR!! \n"); rafacividanes> rafacividanes> //print the recovered plaintext as a string rafacividanes> printf("\n recovered_plaintext1: \n %s \n", recover_msg); rafacividanes> rafacividanes> //print the recovered plaintext as an array rafacividanes> printf("\n recovered_plaintext2: \n "); rafacividanes> for (i=0;i<=size_recover_msg;i++) printf("%c",recover_msg[i]); rafacividanes> rafacividanes> //print the resultt of finalization phase rafacividanes> printf("\n\n final: %s \n", final); rafacividanes> printf("\n size_final = %d \n", size_final); rafacividanes> rafacividanes> EVP_CIPHER_CTX_cleanup(&ctx); rafacividanes> rafacividanes> }//end main rafacividanes> rafacividanes> Another thing I coundn't understand is why rafacividanes> "recovered_plaintext1" sometimes ataches trash when rafacividanes> printed in the screen, and sometimes doesn't. That "trash" is there because you didn't allow EVP_Decrypt_Final_ex() to do it's job properly, by directing it's output to final. You might also notice that the output "recovered_plaintext2" is missing a bit. The last few bytes ended up in final instead, *added* *by* *EVP_DecryptFinal_ex()*! Your decryption should look like this: //Decryption if (!EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc( ), NULL, key, iv)) printf("\n ERROR!! \n"); if (!EVP_DecryptUpdate(&ctx, recover_msg, &size_recover_msg, outbuf, outlen)) printf("\n ERROR!! \n"); if (!EVP_DecryptFinal_ex(&ctx, recover_msg + size_recover_msg, &size_final)) printf("\n ERROR!! \n"); //print the recovered plaintext as a string printf("\n recovered_plaintext1: \n %s \n", recover_msg); //print the recovered plaintext as an array printf("\n recovered_plaintext2: \n "); for (i=0;i<=size_recover_msg + size_final;i++) printf("%c",recover_msg[i]); //print the resultt of finalization phase printf("\n\n final: %s \n", recover_msg + size_recover_msg); printf("\n size_final = %d \n", size_final); And oh, you will still potentially get trash by "recovered_plaintext1". The reason is that you didn't include the ending NUL byte in the text to encrypt, so there's no guarantee you'll get a NUL byte in the proper place in the recovered plaintext either. You should either trust the total returned size of the recovered plaintext, or make sure the NUL byte becomes part of the encrypted text. The latter can be done by using sizeof(intext) instead of strlen(intext). Cheers, Richard ----- Please consider sponsoring my work on free software. See http://www.free.lp.se/sponsoring.html for details. -- Richard Levitte [EMAIL PROTECTED] http://richard.levitte.org/ "When I became a man I put away childish things, including the fear of childishness and the desire to be very grown up." -- C.S. Lewis ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]