我对加密知之甚少,但我能够让 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));
}
这些是根据 mcrypt 的 PHP 文档页面上的评论稍微修改的。(我从 dev_urandom 更改为 rand,因为我在一个 windows 盒子上,其中 dev_urandom 不可用。)
无论如何,我在这个函数中使用的键是这样定义的:
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);
}