我对加密知之甚少,但我能够让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_urandom变为rand,因为我在一个Windows框中,dev_urandom不可用。)
无论如何,我在这个函数中使用的键定义如下:
define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));
我这样称呼我的功能:
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);
}
答案 0 :(得分:5)
此加密服务可能正在使用与CBC不同的分组密码操作模式。如果在CBC模式下使用null iv,那么ECB和CBC的第一个块(在这种情况下为16个字节)将产生相同的密文。任何人都不应该出于任何原因使用ECB模式。
以下是ECB模式加密消息的示例:
答案 1 :(得分:1)
我和我的一所大学,编写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"));
}