3
$\begingroup$

I am encrypting and storing sensitive values in the database. I have a set max length in the database, but in order to provide useful user feedback, I'd like to know the max input I should allow for a given database length.

I can throw together a test that brute forces an answer, but I'd like to understand more generally how to go about calculating.

In my specific case, I'm using Twofish in CBC mode with PKCS7 padding. The result is stored as base64 encoded string. The database column is a VARCHAR(512) column.

I know base64 has an overhead of about 137% of input so, roughly, 512/1.37 = ~373. But now where? is 373, which happens to be 23 blocks, the maximum size, or is there more to it?

Thank you very much for your patience. :)

$\endgroup$

1 Answer 1

5
$\begingroup$

Well, to figure out this sort of thing, it's easier if we work backwards.

So, we start at the back (the fact that we can store up to 512 characters in a database field), and consider how much binary data we can store. Well, base-4 takes 3 bytes of binary data, and encodes it in 4 bytes of base-64. Thus, we can store 3*(512/4) = 384 bytes of binary encrypted data in 512 bytes of base 64.

Now, once we can store up to 384 bytes of encrypted data, we need to consider how much plaintext that corresponds to. Well, you don't specifically mention an IV; in this situation, we might guess that the encryptor selects a random 16 byte IV and sets the first 16 bytes of the ciphertext to that. The second thing to consider is whether the encryptor adds a message authentication code; that is a cryptographical check value that will allow you to detect if someone else modified the database field. Now, you don't mention that you have one, so we'll assume that you do not. This gives us a ciphertext region of 384-16 = 368 bytes.

Lastly, you mention that you use CBC mode with PKCS7 padding. CBC mode always generates a ciphertext that's a multiple of 16; 368 is already a multiple of 16, so we don't loose any room there. In addition, the length of the ciphertext is exactly the length of the padded plaintext; you mention PKCS7 padding, which always adds at least 1 character of padding; this gives us a final value of 367 bytes of plaintext which can fit.

$\endgroup$
4
  • $\begingroup$ Can VARCHAR(512) actually store 512 or does it need some sort of end-of-string marker? $\endgroup$
    – Eyal
    Commented Aug 18, 2012 at 11:13
  • $\begingroup$ @Eyal: the 512 means that the database can store up to 512 characters in that column. If the database has any internal end-of-string designations, the database will take care of it itself. $\endgroup$
    – poncho
    Commented Aug 18, 2012 at 13:39
  • $\begingroup$ if a plain text is already a multiple of the block size, shouldn't you be adding one additional block as a padding? $\endgroup$
    – ultrajohn
    Commented Aug 20, 2012 at 4:26
  • $\begingroup$ @ultrajohn Yes, you would, but 367 is not a multiple of the block size. Actually, with PKCS#7 padding, the maximum plaintext size will always be a multiple of the block size, plus a block with one byte fewer than the block size. Remember that we were working backwards! (sorry for the late reply, but other's may have the same question so I thought I should clarify it none-the-less). $\endgroup$
    – Maarten Bodewes
    Commented Feb 26, 2023 at 1:26

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.