PHP AES加密......不知道我在做什么

Bra*_*rad 3 php encryption aes mcrypt

我对加密知之甚少,但我能够让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)); 
} 
Run Code Online (Sandbox Code Playgroud)

这些是对mcrypt的PHP文档页面上的注释稍作修改的.(我从dev_urandom更改为rand,因为我在windows框中,dev_urandom不可用.)

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

define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));
Run Code Online (Sandbox Code Playgroud)

我把这个函数称为:

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

现在,生成的十六进制字符串的前16个字节(32位)很好.接下来的16个字节与预期的不匹配.

请参阅,我将此数据发布到外部Web服务,然后将其解密.我(遗憾的是)不能给出我没有分发加密密钥和数据的测试用例.我非常抱歉,但我希望熟悉mcrypt的人可以看看这个并告诉我我做错了什么.

再次,对于缺乏可靠的测试用例感到遗憾,但我非常感谢您提供的任何帮助!

编辑:我发布的似乎是我的提供商正在使用null 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); 
}
Run Code Online (Sandbox Code Playgroud)

roo*_*ook 5

该加密服务可能正在使用与CBC不同的分组密码操作模式.如果在CBC模式下使用null iv,那么ECB和CBC的第一个块(在这种情况下为16个字节)将产生相同的密文.任何人都不应以任何理由使用ECB模式.

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

替代文字