I'm trying to understand how padding works when using block ciphers.

Padding may be required when the size of the plain text is not a multiple of the block size

If that's so, then I don't understand the results I am getting on my Ubuntu VM.

I created a .txt file in size of 20 bytes, encrypted it using AES128-ECB. I then ran a command to check the encrypted .bin file size and it was 32 bytes as expected.

What I don't understand is the following scenario — I created another .txt file, this time in size of 32 bytes, encrypted it using same method and when I checked the encrypted file's size I got 48 bytes and not 32.

My question is why is it I am getting 48 bytes instead of 32? Obviously this time the plain text's size was a multiple of the block size and yet it treated it as if it wasn't.

  • $\begingroup$ Unless you're studying how message encryption schemes work, you should forget that padding exists, and forget that block ciphers exist. Instead, you should focus on security contracts of composite things like AES-GCM and NaCl crypto_secretbox_xsalsa20poly1305. And you should definitely forget that ECB exists except as a bad word until you understand what pseudorandom permutation families are and how to reason about them. $\endgroup$ – Squeamish Ossifrage May 6 '18 at 20:33

The padding scheme being used in your example for the block cipher is PKCS#7 Padding.

This scheme specifies that:

The value of each added byte is the number of bytes that are added, i.e. N bytes, each of value N are added.

The thing is, if the plaintext is multiple of the block size, then a whole new padding block is added. In this case it will be a block of 16 bytes with value 16.

 This is necessary so the deciphering algorithm can determine with certainty whether the last byte of the last block is a pad byte indicating the number of padding bytes added or part of the plaintext message.

That's why your ciphertext has a size of 48 bytes when the plaintext is 32 bytes. That is one ciphertext byte for each plaintext plus a whole new block of padding

  • $\begingroup$ Note: In many library implementations AES PKCS#7 Padding is specified as PKCS#5 Padding. $\endgroup$ – zaph May 6 '18 at 18:10

Padding needs to be a one to one (meaning unambiguous) operation. If it weren't then that implies there must be $Pad(M_1) = Pad(M_2)$ for distinct messages $M_1$ and $M_2 $. (Messages differing in length in your case.)

A padding function that adds only enough bytes to be one block longer while also using zero pad bytes if the plaintext size is an exact multiple of the block size cannot exist. This is because you have $2^{128}$ possible inputs 16 bytes long plus all inputs less than 16 bytes long which is less than the number of output blocks (which is also $2^{128}$.

And if your padding function isn't one to one, then you can get $E_K(Pad(M_1)) = E_K(Pad(M_2))$. If you were to decrypt the two ciphertexts, then for both files you get the same result. Perhaps either $M_1$ or $M_2$. If your padding function is not losslessly reversible then your encryption function would not be losslessly reversible either.

So in your case it isn't surprising that an input file with length equal to AES's block size has a ciphertext form that is padded out one block longer.

It would be surprising if you tried decrypting the two .bin files (that were originally .txt files of unequal length) and got back two identical decrypted files.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.