I found something strange while checking the inside of the envelope data.

I had plain text "plaintextplant" - length is $15$ (include lf(0x0A))`. I made a .ber file that is encrypted by AES256 and encoded DER via:

openssl cms -encrypt -in plain -aes256 -recip certificate.pem -outform DER -out enveloped-data.ber

Then, I checked the encrypted data through berReader. I thought that the encrypted data is 16 bytes long because the length of the plain text is $15$. However, the length of the result is $32$ bytes.

enter image description here

So, I typed:

openssl enc -aes-256-cbc -in plain -out enc -k 123 ,for get a encrypted data.

Then, I checked the length of encrypted data is $16$ bytes in output data.

I give you pictures of the result:

enter image description here

Why is the size of the cms encrypted data 32 bytes?

Plus, I attach the picture that the length of the plain text is 13 bytes. Its encrypted data size is 16bytes. enter image description here


2 Answers 2


openssl cms -encrypt/sign by default applies SMIME canonicalization -- even when the output format isn't SMIME. This changes LF to CRLF making the data 16 bytes, padded to 32. To see this look at

 openssl cms -decrypt -in yourcmsder -inform der -recip cert -inkey privkey | od -tx1

To prevent this, add -binary on the encrypt. See the man page on your system or on the web.

Also, as kelalaka says, enc -k (and also -kfile -pass or no option which prompts) does password-based encryption that derives the key and IV from the password and salt (which is normally random but can be specified with -S or suppressed with -nosalt). You can get a result closer to the data in cms -encrypt, but without the canonicalization, with something like

openssl enc -aes-cbc-256 -in plain -K (hexupto64) -iv (hexupto32) -out encrypted
# note uppercase K not lowercase k
# key,iv are padded if needed so just 00 for each is okay for test

This doesn't do the key derivation, so it doesn't use salt, and thus doesn't store the salt in the encrypted output.


AES is a block cipher and needs a proper mode of operation like CBC, CTR, and so on.

While the streaming modes like CFB, OFB, and CTR don't require padding the CBC and ECB mode of operations requires padding.

In CBC mode the usual padding is the PKCS#7 padding. For CBC encryption the message is divided into 128-bit blocks and the padding is applied into the last block. There can be two cases;

  1. The message has missed some bytes; in this case, let $n$ is the number of missing bytes, then the number $n$ is added $n$ times as a byte.

    [Message Bytes    ][01]       // 1 Byte is missing
    [Message Bytes  ][0202]       // 2 Bytes are missing 
    [Message Bytes][030303]       // 3 Bytes are missing
    [MB][0F0F0F...0F0F0F0F]       // 15 Bytes are missing
  2. The message is multiple of 16-byte, this means that the last block is full. In this case, to distinguish this case from the first case we add a new block full of 10s. Therefore, we can have the reverse of the padding. One can see the reason as to what if the last block has 01 as the last byte. Is it padding or not? So adding 01 removes this ambiguity.

The above can explain why a message becomes a multiple of 16 bytes after proper CBC encryption.

In the case of the question, 15 bytes can become 16 bytes by adding 01 as the last byte. What about the remaining 16-bytes?

CBC mode of operation needs a 16-byte random and unpredictable Initialization Vector (IV) to achieve Ind-CPA security.

IV is one of the requirements for the decryption of the first block other than the key ( key, IV, and $C_0$ is required);

$$P_0 = \operatorname{AES-DEC}(key,C_0) \oplus IV$$

Therefore the IV must be added/transferred, too. In the usual practice, the IV is appended to ciphertext.

What if IV is not stored/transferred? Well, you will lose only the first block of the message, the rest can be decrypted properly since;

$$P_i = \operatorname{AES-DEC}(key,C_i) \oplus C_{i-1}, \quad i \geq 1$$


The CMS requires

The AlgorithmIdentifier parameters field MUST be present, and the parameters field MUST contain a AES-IV:


The IV is stored in the AlgorithmIdentifier field, not in the encryptedContent As Dave wroted it is -binary issue.

  • OpenSSL option -k

    The IV and Key are derived from the key derivation method by using the user's password and the 8-byte random salt. The IV is not prepended.

    OpenSSL first outputs the magic word Salted__ then 8-byte salt then the ciphertext into the file. Now the output size is your magic size + salt size + ciphertext-size

  • $\begingroup$ Shoot me if I'm wrong about CMS.. $\endgroup$
    – kelalaka
    Commented Dec 30, 2021 at 14:59
  • $\begingroup$ I don't think shooting is justified, but you are wrong; as stated in the first two lines of your quote, the IV is in the parameters part of the AlgorithmIdentifier, not appended (or prepended) to the ciphertext in encryptedContent. $\endgroup$ Commented Dec 31, 2021 at 5:00
  • $\begingroup$ I see, I've little update to remove the incorrect leading part. Thanks. $\endgroup$
    – kelalaka
    Commented Dec 31, 2021 at 9:22
  • $\begingroup$ Thanks to you, I learned about AES-IV field in CMS. $\endgroup$
    – poiuy925
    Commented Jan 5, 2022 at 4:29
  • $\begingroup$ FYI, once you get 15 reputations you can upvote, too. in SO, upvote if the answer is helpful to you, accept if solves the problem. $\endgroup$
    – kelalaka
    Commented Jan 5, 2022 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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