代码之家  ›  专栏  ›  技术社区  ›  Brad

php-aes加密…不知道我在做什么

  •  3
  • Brad  · 技术社区  · 14 年前

    我对加密不太了解,但我能让AES在PHP中工作…有点。下面是我使用的几个函数:

    function aes_decrypt($val,$ky) 
    { 
        $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
        for($a=0;$a<strlen($ky);$a++) 
          $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
        $mode = MCRYPT_MODE_ECB; 
        $enc = MCRYPT_RIJNDAEL_128; 
        $dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND) ); 
        return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
    } 
    
    function aes_encrypt($val,$ky) 
    { 
        $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
        for($a=0;$a<strlen($ky);$a++) 
          $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
        $mode=MCRYPT_MODE_ECB; 
        $enc=MCRYPT_RIJNDAEL_128; 
        $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
        return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
    } 
    

    这些是从一个 comment on the PHP documentation page for mcrypt . (我从dev_random改为rand,因为我在一个Windows框中,dev_random不可用。)

    无论如何,我在此函数中使用的键的定义如下:

    define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));
    

    我这样称呼我的函数:

    echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));

    现在,得到的十六进制字符串的前16个字节(32位)就可以了。接下来的16个字节与预期不匹配。

    请看,我正在将此数据发布到一个外部Web服务,该服务随后对其进行解密。不幸的是,如果不交出加密密钥和数据,我就无法给出一个测试用例。对此我非常抱歉,但我希望熟悉Mcrypt的人能看看这个,告诉我我做错了什么。

    再次,对于缺乏一个可靠的测试用例感到抱歉,但是我非常感谢您能提供的任何帮助!

    编辑: 我要发布到的提供商似乎正在使用空IV。按照Rook的建议,我已切换到CBC模式,并删除了与密钥相关的不必要代码。以下是我的新功能:

    function aes_decrypt($val,$key)
    {
        $mode = MCRYPT_MODE_CBC;
        $enc = MCRYPT_RIJNDAEL_128; 
        $dec = @mcrypt_decrypt($enc, $key, $val, $mode, null); 
        return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
    }
    
    function aes_encrypt($val,$key) 
    {
        $mode = MCRYPT_MODE_CBC;
        $enc=MCRYPT_RIJNDAEL_128; 
        $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
        return mcrypt_encrypt($enc, $key, $val, $mode, null); 
    }
    
    2 回复  |  直到 10 年前
        1
  •  5
  •   rook    14 年前

    很可能这个加密服务使用了不同的块密码操作模式,如CBC。如果空IV与CBC模式一起使用,那么ECB和CBC的第一个块(在本例中为16字节)将生成相同的密码文本。任何人不得出于任何原因使用ECB模式。

    以下是ECB模式加密消息的示例:

    类似于CBC的不同分组密码操作模式。如果空IV与CBC模式一起使用,那么ECB和CBC的第一个块(在本例中为16字节)将生成相同的密码文本。任何人不得出于任何原因使用ECB模式。

    以下是ECB模式加密消息的示例:

    alt text

        2
  •  1
  •   Moddinu    10 年前

    我和我的一所大学,在那里编写了一个iPhone应用程序,并使用上述方法对数据进行加密和解密。但当我加密要从他的iPhone读取的数据时,我们发现了一个问题。iPhone使用了pkcs7填充。上面的代码添加了额外的填充,这将导致iPhone解密方法失败。我们修改了代码以解决当前问题:

    public static function  aes128Encrypt($key,$val) 
    {
        $mode = MCRYPT_MODE_CBC;
        $enc=MCRYPT_RIJNDAEL_128; 
        $blocksize= mcrypt_get_block_size($enc,$mode);
        $stringLength = strlen($val);
        $paddingLength =$blocksize-($stringLength%$blocksize);
        $val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength));
        return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")); 
    }