I have a C# solution that encrypts a bunch of small data chunks using AES.

        //This is how I'm configuring the Aes object
        var aes = Aes.Create();
        aes.Mode = CipherMode.CBC;
        aes.KeySize = 256;
        aes.Padding = PaddingMode.PKCS7;

I then write the raw ciphertext bytes to SQL Server VARBINARY columns.

Querying the length of these VARBINARY ciphertext columns I expected them to always be a multiple of 16 bytes. However that does not appear to be the case here.

I tried reading up about it online and the only questions I found are asking why AES ciphertext is padded up to 16 byte blocks, so I thought I'd ask about the inverse question here.


  • I tested decrypting one of these oddly sized ciphertexts and it worked fine, so the ciphertext is not malformed.
  • I noticed it doesn't happen often, in one run it happened 19 times out of 5,828.
  • When it does happen it's always off-by-one (31 instead of 32, 767 instead of 768, etc..)

I had a thought that maybe the AES standard might truncate cipher-bytes that are exactly zero (or some other well known number) from the end of the output since that could just be rebuilt by the decryptor? But would love clarification.


2 Answers 2


You are correct; standard AES-CBC (without, say, ciphertext stealing) has an output that is always a multiple of 16 bytes in length.

One possibility that occurs to me that if your AES implementation has a glitch were if the last byte happened to be 0x00, then it wouldn't actually output it (and in the decrypt direction, if the ciphertext was short a byte, it'd implicitly add an 0x00).

If this hypothesis were the case, then in your 5,828 test cases, we'd expect to see the last ciphertext byte be 0 (and hence truncated) an expected 22.8 times; 19 times is well within a standard deviation, and so it is plausible...

  • 2
    $\begingroup$ Note that in that case you could have an off-by two once in 65536 (so likely you just didn't encounter it yet), off by 3 once in ~4 billion etc. Just saying because adding a single byte might not fix the issue (if it needs fixing). I've also seen a lot of issues with testing the binary size, such as retrieving the binary and then testing the size using a string-based function (e.g. strlen in C). Actually, I'd think that is more likely than an error in the encryption / decryption routines - although the implementations in most DB are terrible as well. $\endgroup$
    – Maarten Bodewes
    Commented Apr 2, 2022 at 10:13
  • $\begingroup$ I pulled out one of the values that SQL Server claims is 31 bytes, but the value returned is 32 hexpairs long, so I think @MaartenBodewes is right and SQL Server is actually just reporting the length wrong when I use the LEN function. What I find MORE interesting though is the last byte in all of these is not 00, but 20, which I believe is the ASCII space character? Maybe LEN treats it as a string and tries to auto-trim the strings? In any case this is no longer a crypto question I think. EDIT: Just learned about the DATALENGTH function, which is what I should have been using. $\endgroup$
    – Barak Gall
    Commented Apr 4, 2022 at 17:37

Ok, as others have indicated the standard would always produce a ciphertext with a length that is a multiple of 16 bytes. The issue was when I was measuring the length I had used the T-SQL LEN function which seems to trim 0x20 bytes off the end of binary sequences when it measures the length.

I have now learned that I should be using the DATALENGTH function which does not do this trimming, and when I tried it all values are multiples of 16.

Apologies for the confusion!

  • 1
    $\begingroup$ To clarify - that is even the expected (albeit peculiar) behaviour of T-SQL: "LEN excludes trailing spaces" as per e.g. the official documentation $\endgroup$
    – Morrolan
    Commented Apr 4, 2022 at 20:01
  • $\begingroup$ Yeah that makes a lot more sense then. Thanks @Morrolan $\endgroup$
    – Barak Gall
    Commented Apr 5, 2022 at 2:16

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.