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

发布于 2024-10-03 13:22:51 字数 2445 浏览 1 评论 0原文

我对加密不太了解,但我能够在 PHP 中使用 AES......有点。以下是我正在使用的几个函数:

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); 
}

I don't know much about encryption, but I was able to get AES working in PHP... somewhat. Here are a couple functions that I am using:

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)); 
} 

These are slightly modified from a comment on the PHP documentation page for mcrypt. (I changed from dev_urandom to rand, as I am on a windows box, where dev_urandom is not available.)

Anyway the key I use in this functions is defined like this:

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

I call my function like this:

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

Now, the first 16 bytes (32 digits) of the resulting hex string are fine. The next 16 bytes do not match what is expected.

See, I am posting this data to an external webservice that then decrypts it. I (unfortunately) can't give the one test case I have without handing out my encryption key and data. I am terribly sorry about that, but I am hoping someone familiar with mcrypt can look at this and tell me what I am doing wrong.

Again, sorry about the lack of a solid test case, but I am greatly appreciative of any help you can give!

EDIT: It seems my provider that I am posting to is using a null IV. Following Rook's advice, I have switched to CBC mode, and removed the unnecessary code related to the key. Here are my new functions:

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); 
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傲娇萝莉攻 2024-10-10 13:22:51

该加密服务很可能使用不同的分组密码操作模式,例如 CBC。如果 CBC 模式使用空 iv,则 ECB 和 CBC 的第一个块(在本例中为 16 字节)将产生相同的密文。任何人都不应以任何理由使用 ECB 模式。

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

alt text

It is likely that this encryption service is using a different block cipher mode of operation like CBC. If a null iv is being used with CBC mode then the first block (in this case 16 bytes) of ECB and CBC will produce the same cipher text. ECB mode should never be used by anyone for any reason.

Here is an example ECB mode encrypted message:

alt text

抹茶夏天i‖ 2024-10-10 13:22:51

我和我的一所大学正在编写 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")); 
}

Me and a college of mine where coding an iPhone app and where using the above methods to encrypt and decrypt data. But we found an issue when I was encrypting the data to be read from his iPhone. The iPhone used PKCS7 padding. The above code was adding extra padding this would cause the iPhone decryption method to fail. We amended the code to fix the current issue :

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")); 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文