PKCS7-PKCS5-填充算法

45次阅读

共计 1594 个字符,预计需要花费 4 分钟才能阅读完成。

PKCS7

PKCS7是当下各大加密算法都遵循的填充算法,且 OpenSSL 加密算法簇的默认填充算法就是 PKCS7

其实 PKCS7 理解起来非常简单,使用需填充长度的数值 paddingSize 所表示的 ASCIIpaddingChar = chr(paddingSize)对数据进行冗余填充。

为什么是冗余填充呢?因为即便你的数据长度符合 blockSize 的整数倍时,也需要填充,填充的长度反而是最大的,要填充 blockSizechar(blockSize)字符在数据尾部,这样牺牲了数据长度的做法是为了更为灵活透明的去解包数据,发送端和接收端不需要约定好blockSize,接收端总能通过数据包的最后一个字符得到填充的数据长度。

当我们拿到一串 PKCS7 填充的数据时,取其最后一个字符 paddingChar,此字符的ASCII 码的十进制 ord(paddingChar) 即为填充的数据长度paddingSize,读取真实数据时去掉填充长度即可substr(content, 0, -paddingSize)

填充示例,比如数据块 blockSize 为 8

h<0x07><0x07><0x07><0x07><0x07><0x07><0x07> 7
he<0x06><0x06><0x06><0x06><0x06><0x06> 6
hel<0x05><0x05><0x05><0x05><0x05> 5
hell<0x04><0x04><0x04><0x04> 4
hello<0x03><0x03><0x03> 3
hello <0x02><0x02> 2
hello w<0x01> 1
hello wo<0x08><0x08><0x08><0x08><0x08><0x08><0x08><0x08> 8 // 数据块
hello wor<0x07><0x07><0x07><0x07><0x07><0x07><0x07> 7
hello word<0x06><0x06><0x06><0x06><0x06><0x06> 6

实现:

/**
 * PKCS7 填充
 * @param string $content    待填充内容
 * @param int    $block_size 待填充内容数据块长度
 */
function pkcs7_padding($content, $block_size)
{if (255 < $block_size || 0 >= $block_size) {throw new \Exception("the block size pkcs7 can padding is (0 ~ 255]");
    }

    // 待填充的长度
    $padding_size = $block_size - (strlen($content) % $block_size);
    // 待填充的字符
    $padding_char = chr($padding_size);
    $content .= str_repeat($padding_char, $padding_size);

    return $content;
}

/**
 * 移除 PKCS7
 * @param string $content
 * @return string
 */
function pkcs7_strip($content)
{$padding_char = substr($content, -1);
    $padding_size = ord($padding_char);
    $content      = substr($content, 0, -$padding_size);

    return $content;
}

$content = pkcs7_padding("hello", $block_size);
echo pkcs7_strip($content);

PKCS5

pkcs5作为 pkcs7 的子集算法,概念上没有什么区别,只是在 blockSize 上固定为 8 位,即数据始终会被切割成 8 个字节的数据块,然后计算需要填充的长度。pkcs7的填充长度 blockSize1~255

正文完
 0