1
$\begingroup$

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?

$\endgroup$
5
$\begingroup$

PKCS7 uses mandatory padding. Even if the length of your data is a multiple of your block size, it will pad.

output_size = input_size + (block_size - (input_size % block_size))
$\endgroup$
3
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ 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) $\endgroup$ – dave_thompson_085 Dec 18 '17 at 1:30
1
$\begingroup$

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.

$\endgroup$
  • 1
    $\begingroup$ That's without IV, thus unsafe for multiple encryptions! Most serious programs will add an IV, and the size will be different, and larger. $\endgroup$ – fgrieu Dec 17 '17 at 13:16
  • $\begingroup$ 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. $\endgroup$ – Marc Dec 17 '17 at 13:26

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.