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

Decrypted buffer padding

75 views
Skip to first unread message

Nico Flink

unread,
Dec 1, 2011, 6:31:18 AM12/1/11
to

Hello,

 

I am trying to decrypt a buffer whose size is a multiple of the padding size (n * 16 bytes). But instead of getting the whole buffer as a result from EVP_CipherUpdate() I only get “InSize – PaddingSize” decrypted bytes. I get this behaviour with padding enabled and disabled. Is this the correct behaviour and is there anything I can do about it? In my application I need the insize to equal the outsize.

 

Thanks a lot for your help.

 

Cheers

Nico

 

Andrea Saracino

unread,
Dec 1, 2011, 6:31:23 PM12/1/11
to
Hi,
after you use the EVP_CipherUpdate(), you have to call the EVP_CipherFinal() to encrypt the remaining bytes. Refer to the documentation to see how to correctly pass the parameters: http://www.openssl.org/docs/crypto/EVP_EncryptInit.html. The same goes for the decryption.
 
I hope this help.
 
Cheers.
 
Andrea

Nico Flink

unread,
Dec 2, 2011, 2:32:23 AM12/2/11
to

Hi,

 

Thanks for your reply.

 

I am aware of CipherFinal() but I wonder why CipherUpdate() writes anything into the final buffer at all if the buffer size is a multiple of the padding size. Additionally CipherFinal() fails if I call it afterwards.

 

The documentation says “as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1)”. From that I take it that usually the final buffer should only contain data of the size “cipher_block_size – 1” which is not the case with the described behaviour.

 

Cheers

Nico

 


Andrea Saracino

unread,
Dec 2, 2011, 7:58:48 AM12/2/11
to
Hi again,

Hi,

 

Thanks for your reply.

 

I am aware of CipherFinal() but I wonder why CipherUpdate() writes anything into the final buffer at all if the buffer size is a multiple of the padding size.

 

It looks a bit strange. The CipherUpdate() should implement a symmetric block cipher. Thus, the CipherUpdate() should write anything into the final buffer if the buffer size is multiple of the block size. If don't, the CipherFinal() will encrypt the exceeding bytes.
 

Additionally CipherFinal() fails if I call it afterwards.

 

Consider that I'm only a beginner OpenSSL user, anyway, I suggest to use the EVP_EncryptUpdate() and the EVP_EncryptFinal_ex(), they worked fine for me.

 

 

 

The documentation says “as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1)”. From that I take it that usually the final buffer should only contain data of the size “cipher_block_size – 1” which is not the case with the described behaviour.

 

Cheers

Nico

 

 

Cheers
 
Andrea 

Dave Thompson

unread,
Dec 2, 2011, 5:47:12 PM12/2/11
to
> From: owner-ope...@openssl.org On Behalf Of Nico Flink
> Sent: Friday, 02 December, 2011 02:32

> I am aware of CipherFinal() but I wonder why CipherUpdate()
> writes anything into the final buffer at all if the buffer size
> is a multiple of the padding size. Additionally CipherFinal()
> fails if I call it afterwards.

Cryptographic padding, and in particular the PKCS#5 padding which
is most widely used and OpenSSL defaults to, ALWAYS adds at least
one byte to the data. In this respect it is not like typical
database or COBOL (or FORTRAN!) padding which is not added
if the data is 'full' (already the specified size).

When padding is used (only for a block cipher in block mode),
DecryptUpdate or CipherUpdate in decrypt mode will only decrypt
and return the blocks known to be application data, i.e. followed
by at least one more byte of ciphertext (typically one more block
since you usually send/receive or store/fetch ciphertext in binary
units of at least the cipher blocksize). DecryptFinal or CipherFinal
checks that the buffered last block is complete (error if not),
decrypts it, checks the padding is valid (or error) and removes it,
and returns any data (none if the last block is all padding).

> The documentation says "as a result the amount of data written
> may be anything from zero bytes to (inl + cipher_block_size - 1)".
> From that I take it that usually the final buffer should only contain
> data of the size "cipher_block_size - 1" which is not the case
> with the described behaviour.

That figure is for EncryptUpdate and is the worst case to allow
for a series of calls with varying alignment. In particular if
you have B-1 bytes buffered (from previous call) and 'add' NB+1
bytes, you get NB+B=(NB+1)+(B-1) encrypted. For DecryptUpdate
the man page says inl+B which I think is actually conservative.
But if you put the output from Update(s) + Final into a single
buffer, which you usually do, the combined total is:
- no padding: output = input
- encrypt padded: input + 1 <= output <= input + NB
- decrypt padded: input - NB <= output <= input - 1

<snip>

> Il giorno 01 dicembre 2011 12:31, Nico Flink <fl...@coolux.de> ha
scritto:


> I am trying to decrypt a buffer whose size is a multiple
> of the padding size (n * 16 bytes). But instead of getting
> the whole buffer as a result from EVP_CipherUpdate() I only get
> "InSize - PaddingSize" decrypted bytes. I get this behaviour
> with padding enabled and disabled. Is this the correct behaviour
> and is there anything I can do about it? In my application I need
> the insize to equal the outsize.

See above. With padding you should get csize - 16 from Update (or a
series of Updates) and the last 0 to 15 from Final. The total plaintext
size will always be at least 1 byte less than the ciphertext size
(or equivalently ciphertext always at least 1 more than plaintext).
This is inherent in the padding scheme and you must live with it
in order to have arbitrary-length plaintext in a block mode.
Alternatives are:
- use a block mode with no padding and your data must always be
an exact multiple of the block size. This is usually inconvenient.
- use a stream mode or stream cipher

If you decrypt without padding, I don't recall if that actually
turns off buffering, but between Update + Final you should get
plaintext size exactly equal to ciphertext size, which must be
integral blocks (for a block cipher and mode) else error.


______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org

0 new messages