# Can we calculate AES-CBC-PKCS7 ciphertext length based on the length of the plaintext?

I am currently using AES256 in CBC mode with PKCS7 Padding to encrypt some data. It seems like the output size is not always a power of two, which was what I expected.

Is it possible to calculate the size in bytes of the output, knowing only the input data?

output_size = input_size + (block_size - (input_size % block_size))


AES is a block cipher with 128-bit block (regardless of its key size of 128, 192 or 256 bits); that is 16 octets. PKCS#7 padding adds from one octet to a full block. It thus transforms $n$ octets of plaintext into $16\lfloor n/16+1\rfloor$ octets of padded plaintext, where $\lfloor x \rfloor$ $x$ rounded down to integer. Equivalently, the padded size is $n+16-(n\bmod 16)$ octets. In C(++), Java or Go, that's (n|15)+1.

Size of the ciphertext when enciphering in CBC mode is typically larger, because secure use of the CBC mode requires an IV, typically included in the ciphertext, often 8 or 16 octets. With openssl enc -aes-256-cbc the IV is 8 octets, but there is also an 8-octet header (Salted__ in ASCII). So in the end the ciphertext is 16 octets more than the padded plaintext. Again, that depends on the program.

There's no reason that the output size be a power of two in CBC mode, and it usually is not.

• openssl enc is probably not a good example; it stores salt (8 octets regardless of cipher) plus the fixed string Salted__, and derives the IV along with the key; see #3298. For CBC IV is one data block (varies depending on cipher); for GCM and CCM IV would probably be different (plus there would be no block padding) but that doesn't matter because enc format doesn't support any AEAD (or separate auth, for that matter) Dec 18, 2017 at 1:30

I'm not sure where you got the power of two. With AES, your output will always be a multiple of the block size (16 bytes or 128 bits).

With PKCS7, if your input is already a multiple of 16 bytes, then an extra block is added for padding. If your input is not a multiple of 16 bytes, then round up to the nearest multiple of 16.

Some examples:

Input: 1 byte   output: 16 bytes
Input: 15 bytes output: 16 bytes
Input: 16 bytes output: 32 bytes


And a small nit pick: the size is technically determined before AES encryption. The padding is applied first to obtain 16 byte blocks, then AES is applied to everything.

• That's without IV, thus unsafe for multiple encryptions! Most serious programs will add an IV, and the size will be different, and larger.
– fgrieu
Dec 17, 2017 at 13:16
• True, this only talks about the data size itself. How encryption context is stored is up to the user/program. It could be in the same file using a known format, or it could be stored separately from the data.
– Marc
Dec 17, 2017 at 13:26