php:三种填充模式的区别(PKCS7Padding/PKCS5Padding/ZeroPadding)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/panjiapengfly/article/details/102757763

长话短说,写这篇文章主要是为了补下这篇文章的相关知识点 aes加密使用mcrypt_decrypt能解开,openssl_decrypt却解不开。

常见的三种填充方式:

我们知道某些加密算法要求明文需要按一定长度对齐,叫做块大小(BlockSize),比如16字节,那么对于一段任意的数据,加密前需要对最后一个块填充到16 字节,解密后需要删除掉填充的数据。

  • ZeroPadding,数据长度不对齐时使用0填充,否则不填充。使用0填充有个缺点,当元数据尾部也存在0时,在unpadding时可能会存在问题。
  • PKCS7Padding,假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。
  • PKCS5Padding,PKCS7Padding的子集,块大小固定为8字节,填充方式和PKCS7Padding一样。

由于使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据,而使用ZeroPadding填充时,没办法区分真实数据与填充数据,所以只适合以\0结尾的字符串加解密。

字符'0'和'\0',及整数0的区别

php的底层是c,所以以c语言为标准;

字符型char和整型int;

字符型变量用于存储一个单一字符,在 C 语言中用 char 表示,其中每个字符变量都会占用 1 个字节(8位二进制数)。

整型int在内存中占用空间为四个字节(32位二进制数)

字符'0':char c = '0'; 它的ASCII码实际上是48。内存中存放表示:00110000

字符'\0' :ASCII码为0,表示一个字符串结束的标志。这是转义字符(整体视为一个字符)。由于内存中存储字符,依然是存储的是对应字符集的字符编码;所以内存中的表现形式为00000000

整数0 :内存中表示为:00000000 00000000 00000000 00000000;虽然都是0,但是跟上面字符'\0'存储占用长度是不一样的;

php PKCS7Padding和ZeroPadding填充方法如下:

#PKCS7
public static function pad($data, $blocksize = 16)
{
    $pad = $blocksize - (strlen($data) % $blocksize);
    return $data . str_repeat(chr($pad), $pad);
}
                
public static function 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);
}


#zero
public static function padZero($data, $blocksize = 16)
{
    $pad = $blocksize - (strlen($data) % $blocksize);
    return $data . str_repeat("\0", $pad);
}
            
public static function unpadZero($data)
{
    return rtrim($data,"\0");
}

猜你喜欢

转载自blog.csdn.net/panjiapengfly/article/details/102757763