gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 12:03:14 29 4
gpt4 key购买 nike

我在解密之前在 PHP 应用程序中加密的 pgcrypto 数据时遇到问题。

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

一切都在 PHP 中加密解密,但在 pgcrypto 中我可以使用相同的 key 和 iv 仅解密 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, 0, $pad, "8bit");
$data = mb_substr($data, $pad, 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, $key, $data, MCRYPT_MODE_CBC, $iv);
} else {
$data = openssl_decrypt($data, "aes-256-cbc", $key, 0, $iv);
}

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

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

return $data;
}
function e ($data, $key, $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, $key, $data, MCRYPT_MODE_CBC, $iv);
} else {
$data = openssl_encrypt($data, "aes-256-cbc", $key, 0, $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, $key1, $mode1); //
$d2 = d($e2, $key2, $mode2); //
$d3 = d($e3, $key3, $mode3); //

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

用于编码的结果和数据:

1) mcrypt - RIJNDAEL 128 CBC

  • key = "67pma7BQL01cqb6Nlil2T1436lLXv8Ln"
  • 初始化向量 base64 = "q5gXIfW6maT4zx4tgJQImg=="
  • 加密字符串 base64 ="q5gXIfW6maT4zx4tgJQImtwJgEVK66mTcRPdilkEiHY="
  • 解密字符串base64 = "dGVzdA=="

2) mcrypt - RIJNDAEL 256 CBC

  • key = "85f2669023b98a62d1312af75994ddf1"
  • 初始化向量 base64 = "2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco0="
  • 加密字符串 base64 = "2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco3B29CC5DpfWs1YAfh8WuY9f0/6OPC1B4sidSV5TojJ1g=="
  • 解密字符串base64 ="dGVzdAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAA="

3) openssl_encrypt - aes-256-cbc

  • key = "85f2669023b98a62d1312af75994ddf1"
  • 初始化向量 base64 = "tOi+xXZf6MyPDpQzPZAI6Q=="
  • 加密字符串 base64 = "tOi+xXZf6MyPDpQzPZAI6XJQYmwyNUVzKzdaVnNickc5dEg5MUd1anpBYlpLeW9SQjhpZ29yQzRpWFk9"
  • 解密字符串base64= "dGVzdA=="

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

SELECT
-- mcrypt aes 128
decrypt_iv(
decode('q5gXIfW6maT4zx4tgJQImtwJgEVK66mTcRPdilkEiHY=', 'base64'),
'67pma7BQL01cqb6Nlil2T1436lLXv8Ln',
decode('q5gXIfW6maT4zx4tgJQImg==', 'base64'),
'aes-cbc'
),

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

如您所见,所有 3 个都已在 PHP 中解密。仅在 Postgres 中首先 (mcrypt aes128cbc) 解密 OK - 前 16 个字节仍然是 IV,但我可以删除它们并转换为文本。另外两个(mcrypte AES256CBC 和 openssl256cbc)甚至看起来都没有被解密。我用 openssl256cbc 评论了 block ,因为它给了我“[39000] 错误:decrypt_iv 错误:数据不是 block 大小的倍数”错误。

我们将不胜感激。

最佳答案

MCRYPT_RIJNDAEL_256 不是 AES-256。这是 block 大小为 256 的 Rijndael 密码(因此出现错误)。 AES 是 Rijndael 密码的子集,使用 128 位的 block 大小和 128、192 和 256 位的 key 大小。这也反射(reflect)在 IV 尺寸上。

要创建 AES-256 加密密文,您可以使用具有正确 key 大小(256 位为 32 字节)的 MCRYPT_RIJNDAEL_128_128 后缀表示要使用的 block 大小;您仍然可以使用 128、192 或 256 位的任何有效 key 大小。


请注意,mcrypt——尤其是底层的 C 库——已不再维护。您最好使用 openssl 或更高版本的加密库。

mcrypt 和 OpenSSL 包装器也很乐意允许无效的 key 大小,只警告您 - 如果您幸运的话。这当然与任何定义明确的 AES 库都不兼容。

关于php - 无法使用 AES-256-CBC 中的 pgcrypto 解密,但 AES-128-CBC 可以,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43550818/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com