当前位置: 首页 > 知识库问答 >
问题:

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

吴涵育
2023-03-14

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

我尝试了3种类型的加密:
1)mcrypt-rijndael 128 cbc
2)mcrypt-rijndael 256 cbc
3)openssl_encrypt-aes-256-cbc

在PHP中,所有的东西都可以加密解密,但在pgcrypto中,我可以使用相同的密钥和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

  • 键=“67PMA7BQL01CQB6NLIL2T1436LLXV8LN”
  • 初始化向量base64=“q5gxifw6mat4zx4tgjqimg==”
  • 加密字符串base64=“q5gxifw6mat4zx4tgjqimtwjgevk66mtcrpdilkeihy=”
  • 解密字符串base64=“dgvzda==”

2)Mcrypt-Rijndael 256 CBC

    null
    null
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'
    )

正如您所看到的,在PHP中,所有3个都可以解密。在Postgres中,只有第一个(mcrypt aes128cbc)解密的OK-第一个16字节仍然是IV,但我可以删除它们并转换为文本。另外两个(mcrypte AES256CBC和openssl256cbc)看起来甚至不像是被解密的。我用openssl256cbc注释了块,因为它给出了“[39000]error:decrypt_iv error:Data not a multiple of block size”错误。

任何帮助都将不胜感激。

共有1个答案

广乐邦
2023-03-14

mcrypt_rijndael_256不是AES-256。它是Rijndael密码,其块大小为256(因此出现错误)。AES是Rijndael密码的一个子集,使用128位的块大小和128、192和256位的密钥大小。这也体现在IV尺寸上。

要创建AES-256加密密文,可以使用具有正确密钥大小(256位等于32字节)的mcrypt_rijndael_128_128后缀指示要使用的块大小;您仍然可以在128、192或256位的任何有效密钥大小下使用它。

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

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

 类似资料:
  • 问题内容: 我在解密以前在PHP应用程序中加密过的pgcrypto中的数据时遇到问题。 我尝试了3种加密类型: 1)mcrypt-RIJNDAEL 128 CBC 2)mcrypt-RIJNDAEL 256 CBC 3)openssl_encrypt-aes-256-cbc 一切都在PHP中很好地解密,但是在pgcrypto中,我只能使用相同的密钥和iv进行解密1)mcrypt-RIJNDAEL

  • 我希望有一个用C编写的程序,可以在没有openssl这样的大型库的帮助下,用AES-CBC对字符串进行编码/解码。 目标: 使用密码短语对字符串进行编码/解码: 因此,应用程序需要接受3个输入参数。。。 输入字符串(待编码)/或已编码字符串(待解码) 用于编码/解码字符串的密码 编码或解码指示器 我对C语言不熟悉(我可以用C#编码)。 我已经找到了https://github.com/kokke/

  • 我只想用这3种模式测试openSSL中的AES:128192和256密钥长度,但我解密的文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如1024字节)时,我的程序显示。。。我的意见总是一样的,但这并不重要,至少现在是这样。代码如下: 编辑: 当我将输出大小更改为而不是时,我得到了结果: 那么,是否有可能存在Outpus大小和IV大小的问题?它们应该有什么尺寸(AES-CB

  • 我用java编写了这段代码,以便解密密文。我有钥匙。对我来说,一切都是正确的,但我有我要解释的问题。 这是我的代码: 我收到以下错误: 出了什么问题?我知道这个问题在某种程度上与衬垫有关,但我不知道确切的解决方案。我只有一个密文IV和密钥。

  • bouncyCastle新手,欢迎提供帮助。我正在尝试使用bounncycastle java API在我的系统上解密一个由第三方加密的文件。它似乎可以很好地解密文件,除了解密文件开头的一团垃圾数据。代码如下 解密的数据块看起来很好,除了开头的“?”??? 用于解密文件的openssl命令在下面的命令中运行良好。事实上,我在解密时使用的是openssl打印的密钥和iv。 加密文件中的openssl

  • 我正在尝试在python中实现此代码(我是python新手),它给我以下错误: attribute error:“str”对象没有属性“decode” 如果我们删除 只是为了避免这样的错误: 但它给我以下错误: ValueError:IV必须为16字节长 因为算法需要,我必须删除 有没有人知道我该怎么做才能使这段代码工作?