PKCS5Padding和PKCS7Padding唯一不同的地方在于块的大小
在PKCS5Padding中, 明确定义Block的大小是8个字节
而在PKCS7Padding定义中,块的大小是不确定的,可以在1-255字节之间
PKCS5, PKCS7 有如下相同的特点:
1)填充的字节都是一个相同的字节
2)该字节的值,就是要填充的字节的个数
如果要填充8个字节,那么填充的字节的值就是0×8;
要填充7个字节,那么填入的值就是0×7;
…
如果只填充1个字节,那么填入的值就是0×1;
正是这种即使恰好是8个字节也需要再填充字节的规定,可以让解密的数据很确定无误的移除多余的字节。
因为解密恢复的明文的最后一个字节,就能告诉你 存在多少个填充字节
举例:假定块长度为 8,数据长度为 9,
数据: FF FF FF FF FF FF FF FF FF
PKCS7 填充后: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
一种python 实现
pad_len = 8 - (len(data) % self.block_size) if _pythonMajorVersion < 3: data += pad_len * chr(pad_len) else: data += bytes([pad_len] * pad_len) if _pythonMajorVersion < 3: pad_len = ord(data[-1]) else: pad_len = data[-1] data = data[:-pad_len]
另外一种实现
BS = 8 pad = lambda s: s + (BS - len(s) % BS) * bytes([BS - len(s) % BS]) unpad = lambda s : s[0:-(s[-1])] ############# pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) unpad = lambda s : s[0:-ord(s[-1])]
PKCS5 pad/unpad的 PHP实现
function pkcs5_pad ($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } function pkcs5_unpad($text) { $pad = ord($text{strlen($text)-1}); if ($pad > strlen($text)) return false; if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false; return substr($text, 0, -1 * $pad); }
还有一点需要说明的是:
块大小是 加密方案(加密算法)的一种固有属性,对于AES来说,块大小是128位(16字节)
填充是为了 让加密的输入, 匹配 输入块(一般是块加密算法中矩阵)的长度, 而不是 Key的长度。 输入块是 64位, Key可以是128位,256位。
严格来讲, PKCS5Padding 是不能用于 AES的,因为
PKCS5Padding的块大小,是8字节
AES的块大小,是16字节。
如果有人说 AES算法,使用 PKCS5Padding填充时, 实践上,他使用的是 PKCS7Padding
SSL3Padding跟PKCS5Padding只是稍有不同:PKCS5 Padding填充的值是 要填充的字节数, 而SSL 3 Padding 是要填充的字节数 减去1
所以,很容易得到 ssl3padding的php实现
function ssl3_pad ($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad-1), $pad); } function ssl3_unpad($text) { $text_len = strlen($text); $pad = ord($text{$text_len-1}); $pad_len = $pad + 1; if ($pad_len > $text_len) { return false; } if (strspn($text, chr($pad), $text_len - $pad_len) != $pad_len) { return false; } return substr($text, 0, -1 * $pad_len); }