块加密的几种padding方案

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);
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注