Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question on EVP_DecryptFinal_ex

940 views
Skip to first unread message

David Li

unread,
Jul 31, 2014, 8:16:20 PM7/31/14
to
Hi,

I am using openssl 1.0.1h and AES128 CBC mode to encrypt some arbitrary long ASCII string. 
I encountered an issue at decryption. If I use EVP_DecryptFinal_ex then the output is unrecognizable. If I remove the following then the output is OK.

if ((rc = EVP_DecryptFinal_ex(&ctx, debuf, &tmplen)) == 0) {
    printf (" Finalization error: %d\n", rc);
    return -1;
  }

Can anyone explain why? 

David

Thulasi Goriparthi

unread,
Jul 31, 2014, 11:22:17 PM7/31/14
to
You are most probably over-writing the decrypted data you have got with EVP_DecryptUpdate.  Skip the the length that you have already decrypted in debuf. i.e If you have got outlen bytes from DecryptUpdate, you should supply "debuf+outlen" as second argument to EVP_DecryptFinal

David Li

unread,
Aug 1, 2014, 2:46:18 PM8/1/14
to
Hi Thulasi,

You are right! It's a bug on my part.

I have a follow-up question regarding what EVP_DecryptFinal is doing.

 In my case, the original string is 27 bytes long, the ciphertext  length is 48 ( I am using AES-CBC-128). The decrypted plaintext before finalization is 32 but the finalization added 11 more bytes. So the total decrypted len is 43.  

Can you explain where the 11 more bytes are coming from after finalization?  Also It seems OK even if I don't use finalization, 

David

Thulasi Goriparthi

unread,
Aug 1, 2014, 11:10:35 PM8/1/14
to
On Sat, Aug 2, 2014 at 12:16 AM, David Li <dlip...@gmail.com> wrote:
Hi Thulasi,

You are right! It's a bug on my part.

I have a follow-up question regarding what EVP_DecryptFinal is doing.

 In my case, the original string is 27 bytes long, the ciphertext  length is 48 ( I am using AES-CBC-128). The decrypted plaintext before finalization is 32 but the finalization added 11 more bytes. So the total decrypted len is 43.  

I guess, you must be feeding 43 byte (>=32 byte) plaintext  for encryption which outputs 48 byte ciphertext. For 27 byte plaintext, there would only be 32 byte ciphertext, of which, first 16 byte get decrypted with DecryptUpdate to result in first 16 bytes of plaintext, and  last 16 bytes get decrypted with DecryptFinal to result in last 11 bytes of plaintext. (removes padding that gets applied during encryption)

There might be an issue with encrypt too which may be feeding additional 16 bytes (27 + 16) to EncryptUpdate. Do you apply padding yourself for plaintext and send 32 bytes for encryption? If so, you should explicitly tell the encrypt context to skip the padding by calling EVP_CIPHER_CTX_set_padding(&ctx, 0)


Can you explain where the 11 more bytes are coming from after finalization?  Also It seems OK even if I don't use finalization, 

You must always call EncryptFinal/DecryptFinal, These functions will take care of un-aligned last block. EncryptFinal applies the padding and encrypts, and DecryptFinal decrypts the last block and removes the padding.
 

Salz, Rich

unread,
Aug 1, 2014, 11:36:11 PM8/1/14
to

Just wanted to say that Thulasi’s explanations and advice are exactly correct; thanks!

 

-- 

Principal Security Engineer

Akamai Technologies, Cambridge MA

IM: rs...@jabber.me Twitter: RichSalz

 

David Li

unread,
Aug 3, 2014, 7:20:16 PM8/3/14
to
Hi Thulasi/Rich,

Thanks! This prompted me to uncover another bug in the code. I did encrypt an extra block of zeros! Now everything makes sense. 

Can't help to dig a little deeper into this: In AES-CBC mode, the decryption can be paralleled. Is this what the EVP_DecryptUpdate is doing behind the scene? 

For example, I need to break a long string into blocks to use EVP_EncryptUpdate but I only need to feed the ciphertext into EVP_DecryptUpdate once. 

David

Thulasi Goriparthi

unread,
Aug 4, 2014, 7:39:44 AM8/4/14
to
On Mon, Aug 4, 2014 at 4:50 AM, David Li <dlip...@gmail.com> wrote:
Hi Thulasi/Rich,

Thanks! This prompted me to uncover another bug in the code. I did encrypt an extra block of zeros! Now everything makes sense. 

Can't help to dig a little deeper into this: In AES-CBC mode, the decryption can be paralleled. Is this what the EVP_DecryptUpdate is doing behind the scene? 

CBC decryption could be parallelised, but EVP_DecryptUpdate doesn't do it as it uses a single context. IV will be maintained in the context and would be updated only after decryption of each block.

If you strictly want to parallelise, you can do it with considerable changes to your app by maintaining a separate context for each block and initializing all those contexts with corresponding IVs. Though I haven't quantified, I believe, the performance advantage that you try to get by parallelising would be lost in maintaining too many contexts.
  Parallelisation would be adavantageous for hardware multi-core crypto accelerators.

For example, I need to break a long string into blocks to use EVP_EncryptUpdate but I only need to feed the ciphertext into EVP_DecryptUpdate once. 
You don't have to break your input into blocks. EVP_EncryptUpdate can take input of any length. EVP_EncryptUpdate can(not must) be called multiple times when all the input to be encrypted is not available at once. i.e if you have a big file to be encrypted and you have only 4k byte read buffer, you can encrypt it in 4K byte chunks using EncryptUpdate.

baweja...@gmail.com

unread,
Jan 4, 2015, 3:15:57 AM1/4/15
to
I am facing a similar problem with my implementation of AES_256_GCM cipher. I have posted my query on stackoverflow: http://stackoverflow.com/questions/27763420/what-is-the-correct-format-for-final-block-in-evp-decryptfinal-ex-for-decryption

The exact problem is that some garbage value gets appended to my decrypted string. Please have a look at the link given above and help me out.

Thanks
Kunal Baweja
0 new messages