[ Team LiB ] |
5.11 Manually Adding and Checking Cipher Padding5.11.1 ProblemYou want to add padding to data manually, then check it manually when decrypting. 5.11.2 SolutionThere are many subtle ways in which padding can go wrong, so use an off-the-shelf scheme, such as PKCS block cipher padding. 5.11.3 Discussion
Generally, it is not a good idea to add padding yourself. If you're using a reasonably high-level abstraction, padding will be handled for you. In addition, padding often isn't required, for example, when using a stream cipher or one of many common block cipher modes (including CWC, CTR, CCM, OFB, and CFB). Because ECB mode really shouldn't be used for stream-based encryption, the only common case where padding is actually interesting is when you're using CBC mode. If you are in a situation where you do need padding, we recommend that you use a standard scheme. There are many subtle things that can go wrong (although the most important requirement is that padding always be unambiguous[13]), and there's no good reason to wing it.
The most widespread standard padding for block ciphers is called PKCS block padding. The goal of PKCS block padding is that the last byte of the padded plaintext should unambiguously describe how much padding was added to the message. PKCS padding sets every byte of padding to the number of bytes of padding added. If the input is block-aligned, an entire block of padding is added. For example, if four bytes of padding were needed, the proper padding would be: 0x04040404 If you're using a block cipher with 64-bit (8-byte) blocks, and the input is block-aligned, the padding would be: 0x0808080808080808 Here's an example API for adding and removing padding: void spc_add_padding(unsigned char *pad_goes_here, int ptlen, int bl) { int i, n = (ptlen - 1) % bl + 1; for (i = 0; i < n; i++) *(pad_goes_here + i) = (unsigned char)n; } int spc_remove_padding(unsigned char *lastblock, int bl) { unsigned char i, n = lastblock[bl - 1]; unsigned char *p = lastblock + bl; /* In your programs you should probably throw an exception or abort instead. */ if (n > bl || n <= 0) return -1; for (i = n; i; i--) if (*--p != n) return -1; return bl - n; } The spc_add_padding( ) function adds padding directly to a preallocated buffer called pad_goes_here. The function takes as input the length of the plaintext and the block length of the cipher. From that information, we figure out how many bytes to add, and we write the result into the appropriate buffer. The spc_remove_padding( ) function deals with unencrypted plaintext. As input, we pass it the final block of plaintext, along with the block length of the cipher. The function looks at the last byte to see how many padding bytes should be present. If the final byte is bigger than the block length or is less than one, the padding is not in the right format, indicating a decryption error. Finally, we check to see whether the padded bytes are all in the correct format. If everything is in order, the function will return the number of valid bytes in the final block of data, which could be anything from zero to one less than the block length. |
[ Team LiB ] |