微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 无法使用AES-256-CBC中的pgcrypto解密,但AES-128-CBC是可以的

我有问题解密pgcrypto中以前在 PHP应用程序中加密的数据.

我尝试了3种加密方式:
1)mcrypt – RIJNDAEL 128 CBC
2)mcrypt – RIJNDAEL 256 CBC
3)openssl_encrypt – aes-256-cbc

所有内容都在PHP中加密解密,但是在pgcrypto中我可以使用相同的密钥解密而且只有1)mcrypt – RIJNDAEL 128 CBC

这是PHP部分的示例代码

<?PHP
function d ($data,$key,$mode) {
    $data = @base64_decode($data);
    $pad = $mode == MCRYPT_RIJNDAEL_256 ? 32 : 16;
    $iv = mb_substr($data,$pad,"8bit");
    $data = mb_substr($data,mb_strlen($data,"8bit"),"8bit");

    if ($data === null || $data === "") {
        return $data;
    }

    if ($mode == MCRYPT_RIJNDAEL_128 OR $mode == MCRYPT_RIJNDAEL_256) {
        $data = mcrypt_decrypt($mode,$data,MCRYPT_MODE_CBC,$iv);
    } else {
        $data = openssl_decrypt($data,"aes-256-cbc",$iv);
    }

    if ($data === false) {
        throw new Exception("Unable to decrypt data");
    }

    $padding = ord($data[mb_strlen($data,"8bit") - 1]);
    $data = mb_substr($data,"8bit") - $padding,"8bit");

    return $data;
}
function e ($data,$mode) {
    $pad = $mode == MCRYPT_RIJNDAEL_256 ? 32 : 16;
    $iv = openssl_random_pseudo_bytes($pad);

    $padding = 16 - (strlen($data) % $pad);
    $data .= str_repeat(chr($padding),$padding);

    if ($mode == MCRYPT_RIJNDAEL_128 OR $mode == MCRYPT_RIJNDAEL_256) {
        $data = mcrypt_encrypt($mode,$iv);
    } else {
        $data = openssl_encrypt($data,$iv );
    }

    if ($data === false) {
        throw new Exception("Unable to encrypt data");
    }

    return base64_encode($iv . $data);
}

$mode1 = MCRYPT_RIJNDAEL_128;
$key1 = "67pma7BQL01cqb6Nlil2T1436lLXv8Ln";

$key2 = "85f2669023b98a62d1312af75994ddf1";
$mode2 = MCRYPT_RIJNDAEL_256;

$key3 = "85f2669023b98a62d1312af75994ddf1";
$mode3 = "aes-256-cbc";

$data = "test";

$e1 = e($data,$key1,$mode1);
$e2 = e($data,$key2,$mode2);
$e3 = e($data,$key3,$mode3);

$d1 = d($e1,$mode1); //
$d2 = d($e2,$mode2); //
$d3 = d($e3,$mode3); //

//for ($i=1; $i < 4; $i++) {
//   ${"e" . $i} = e($data,${"key" . $i},${"mode" . $i});
//
//    ${"d" . $i} = d(${"e" . $i},${"mode" . $i});
//}

用于编码的结果和数据:

1)mcrypt – RIJNDAEL 128 CBC

> key =“67pma7BQL01cqb6Nlil2T1436lLXv8Ln”
> init vector base64 =“q5gXIfW6maT4zx4tgJQImg ==”
>加密字符串base64 =
“q5gXIfW6maT4zx4tgJQImtwJgEVK66mTcRPdilkEiHY =”
>解密字符串base64 =“dGVzdA ==”

2)mcrypt – RIJNDAEL 256 CBC

> key =“85f2669023b98a62d1312af75994ddf1”
> init vector base64 =“2EmtyH cQA5X5mmtY vpl5FkVwELS9ExrYnFjGGco0 =”
>加密字符串base64 =“2EmtyH cQA5X5mmtY vpl5FkVwELS9ExrYnFjGGco3B29CC5DpfWs1YAfh8WuY9f0 / 6OPC1B4sidSV5TojJ1g ==”
>解密字符串base64 =
“dGVzdAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAA =”

3)openssl_encrypt – aes-256-cbc

> key =“85f2669023b98a62d1312af75994ddf1”
> init vector base64 =“tOi xXZf6MyPDpQzPZAI6Q ==”
>加密字符串base64 =“tOi xXZf6MyPDpQzPZAI6XJQYmwyNUVzKzdaVnNickc5dEg5MUd1anpBYlpLeW9SQjhpZ29yQzRpWFk9”
>解密字符串base64 =“dGVzdA ==”

这里我是如何尝试使用相同的密钥和IV在Postgres中解密此数据.

SELECT
  -- mcrypt aes 128
  decrypt_iv(
      decode('q5gXIfW6maT4zx4tgJQImtwJgEVK66mTcRPdilkEiHY=','base64'),'67pma7BQL01cqb6Nlil2T1436lLXv8Ln',decode('q5gXIfW6maT4zx4tgJQImg==','aes-cbc'
  ),-- mcrypt aes 256
  decrypt_iv(
      decode('2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco3B29CC5DpfWs1YAfh8WuY9f0/6OPC1B4sidSV5TojJ1g==','85f2669023b98a62d1312af75994ddf1',decode('2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco0=',--     -- openssl aes 256
-- decrypt_iv(
--   decode('tOi+xXZf6MyPDpQzPZAI6XJQYmwyNUVzKzdaVnNickc5dEg5MUd1anpBYlpLeW9SQjhpZ29yQzRpWFk9',--   '85f2669023b98a62d1312af75994ddf1',--   decode('tOi+xXZf6MyPDpQzPZAI6Q==',--   'aes-cbc'
-- ),-- pgcrypto same values as mcrypt aes 128 encrypt then decrypt
  decrypt_iv(
    encrypt_iv(
        'test','aes-cbc'),'aes-cbc'
    )

正如你在PHP中看到所有3个解密好的.
在Postgres中只有第一个(mcrypt aes128cbc)解密OK – 前16个字节仍然是IV,但我可以删除它们并转换为文本.
另外两个(mcrypte AES256CBC和openssl256cbc)甚至看起来都没有被解密.
我用openssl256cbc评论了块,因为它给了我“[39000] ERROR:decrypt_iv错误:数据不是块大小的倍数”错误.

任何帮助将不胜感激.

解决方法

MCRYPT_RIJNDAEL_256不是AES-256.这是Rijndael密码,块大小为256(因此错误). AES是Rijndael密码的子集,使用128位的块大小和128,192和256位的密钥大小.这也反映在IV尺寸上.

要创建AES-256加密密文,您可以使用具有正确密钥大小的MCRYPT_RIJNDAEL_128(256位是32字节). _128后缀表示要使用的块大小;您仍然可以使用任何有效的密钥大小128,192或256位.

请注意mcrypt – 尤其是底层的C库 – 不再被维护.你最好使用openssl或更高版本的加密库.

mcrypt和OpenSSL包装器也会愉快地允许无效的密钥大小,只会警告你 – 如果你很幸运的话.这当然与任何定义良好的AES库都不兼容.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐