# Is this how padding can work?

So for block ciphers you need a fixed size block.

If the plaintext length is not a multiple of the block length then you need to pad it.

One way you could do this is that for the last block you just pad the blocks with 0s or some random characters except for the last character of the last block which represents the number of characters padded.

Of course the problem is what happens when the plaintext is a multiple of the block length (i.e. fits exactly). In this case you just add a dummy block of 0s or 1s. Then when you decrypt you know that if you encounter such a dummy block then the previous block has no padding.

-

So, what is the problem? Last byte will contain the block length, so you will know that entire last block is a padding. – Pavel Ognev Nov 19 '12 at 7:16
But it might have that value anyway. How do you distinguish between the padding and the actual ciphertext? – winterfell Nov 19 '12 at 9:34
Padding is applied to plaintext, not ciphertext. – Pavel Ognev Nov 19 '12 at 17:30

## 2 Answers

You normally want to use a fully invertible padding scheme, i.e. a padding scheme with an associated unpadding scheme such that $unpad(pad(X)) = X$ for every $X$.

Assuming you only append data at the end, and don't do different things depending on the content of the message, this means that you always have to append something, even if the message is already of the right length.

In your scheme, in the case of a message which has already the length of a multiple of the block length, you'll have to append a full block ending with a 16 (assuming a 16-byte block cipher like AES). Your unpadding function then reads the last byte, and knows it has to strip off 16 bytes.

You shouldn't do any special-casing with a block of a certain structure only in the case of a full block appended.

But note that you should preferably use standardized schemes to help interoperability - for example PKCS#7-padding works just like your scheme, but with a bit different filling of the padded data. (This, just like your scheme, requires that the number of appended bytes is encodable in a byte, i.e. a block size of less than 256 bytes = 2048 bits. I'm not aware of any common block cipher with a larger block size, but you would need a different padding scheme in this case.)

-

PKCS#7 requires the block size to be no more than 2048 bits, though. Not a problem yet but it might become one in the future. – Thomas Nov 19 '12 at 14:46
@Thomas Yes, of course, it depends on the block size being representable in one byte. The scheme proposed in the question has the same problem. One could modify this by using two bytes for the length, but block ciphers with blocks larger than 2048 are not that often used. (For public key encryption you'll want to use other padding schemes anyways.) – Paŭlo Ebermann♦ Nov 19 '12 at 14:56
Agreed, I think the widest block cipher I've seen yet is Threefish-1024 and nobody really uses that outside Skein. Just thought I'd mention it :) – Thomas Nov 19 '12 at 15:41

It looks fine though you are better off sticking to established standards which already have parsers written. That way you don't have any problems.

To remove the padding, read the last byte, then move that many values back and truncate. In python it would look something like this:

```
p = decrypt(key, ciphertext)
pad_len = p[len(p)-1]
return p[0:len(p)-pad_len]
```

-

Your code is unfortunately not complete.  You need to validate the padding bytes are correct and within a valid range for your blocksize.  PKCS#7 works fairly well as an integrity test for decryption - if the padding characters are ill-formed, either the message itself was corrupted, or a wrong key was used to decrypt.  It has to be handled properly, of course, or this could open up some kind of padding oracle attack similar to those seen in CRIME/BEAST. – John Deters Nov 21 '12 at 15:21
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 2, "mathjax_display_tex": 0, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "github"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "english_confidence": 0.9182125329971313, "perplexity_flag": "middle"}