无法使用AES-256-CBC的pgcrypto解密,但AES-128-CBC可以 [英] Can't decrypt using pgcrypto from AES-256-CBC but AES-128-CBC is OK

查看:200
本文介绍了无法使用AES-256-CBC的pgcrypto解密,但AES-128-CBC可以的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have problem decrypting data in pgcrypto that was previously encrypted in PHP app.

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

I tried 3 types of encryption:
1) mcrypt - RIJNDAEL 128 CBC
2) mcrypt - RIJNDAEL 256 CBC
3) openssl_encrypt - aes-256-cbc

所有内容在PHP中都可以很好地解密,但是在pgcrypto中,我只能使用相同的密钥和iv进行解密1)mcrypt-RIJNDAEL 128 CBC

everything is encrypted decrypted fine in PHP, but in pgcrypto I can decrypt using same key and iv only 1) mcrypt - RIJNDAEL 128 CBC

这是PHP部分的示例代码:

Here is example code for PHP part:

<?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 =="
  • key = "67pma7BQL01cqb6Nlil2T1436lLXv8Ln"
  • init vector base64 = "q5gXIfW6maT4zx4tgJQImg=="
  • encrypted string base64 = "q5gXIfW6maT4zx4tgJQImtwJgEVK66mTcRPdilkEiHY="
  • decrypted string base64 = "dGVzdA=="

2)mcrypt-RIJNDAEL 256 CBC

  • key ="85f2669023b98a62d1312af75994ddf1"
  • 初始向量base64 ="2EmtyH ++ cQA5X5mmtY + vpl5FkVwELS9ExrYnFjGGco0 ="
  • 加密的字符串base64 ="2EmtyH ++ cQA5X5mmtY + vpl5FkVwELS9ExrYnFjGGco3B29CC5DpfWs1YAfh8WuY9f0/6OPC1B4sidSV5TojJ1g =="
  • 解密的字符串base64 = "dGVzdAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAA ="
  • key = "85f2669023b98a62d1312af75994ddf1"
  • init vector base64 = "2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco0="
  • encrypted string base64 = "2EmtyH++cQA5X5mmtY+vpl5FkVwELS9ExrYnFjGGco3B29CC5DpfWs1YAfh8WuY9f0/6OPC1B4sidSV5TojJ1g=="
  • decrypted string base64 = "dGVzdAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAA="

3)openssl_encrypt-aes-256-cbc

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

这是我尝试使用相同的Key和IV在Postgres中解密此数据的方法.

Here how I am trying to decrypt this data in Postgres using same Keys and IV.

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个解密的OK. 在Postgres中,只有第一个(mcrypt aes128cbc)才可以解密-前16个字节仍然是IV,但是我可以删除它们并转换为文本. 另外两个(mcrypte AES256CBC和openssl256cbc)甚至看起来都不像被解密了. 我用openssl256cbc注释了块,因为它给了我"[39000]错误:decrypt_iv错误:数据不是块大小的倍数"错误.

As you see all 3 decrypted OK in PHP. In Postgres only first (mcrypt aes128cbc) decrypted OK - first 16 bytes still are IV, but I could remove them and convert to text. Two others (mcrypte AES256CBC and openssl256cbc) are not even looking like they were decrypted. I commented block with openssl256cbc since it gives me "[39000] ERROR: decrypt_iv error: Data not a multiple of block size" error.

任何帮助将不胜感激.

推荐答案

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

MCRYPT_RIJNDAEL_256 isn't AES-256. It's the Rijndael cipher with a block size of 256 (hence the error). AES is a subset of the Rijndael cipher using block size of 128 bits and key sizes of 128, 192 and 256 bits. This is also reflected in the IV size.

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

To create an AES-256 encrypted ciphertext you can use MCRYPT_RIJNDAEL_128 with the correct key size (256 bits is 32 bytes). The _128 postfix indicates the block size to be used; you can still use it with any valid key size of 128, 192 or 256 bit.

请注意,不再维护mcrypt,尤其是基础C库.最好使用openssl或更高版本的加密库.

Beware that mcrypt - especially the underlying C-library - is not maintained anymore. You're better off using the openssl or later crypto libraries.

mcrypt和OpenSSL包装器也将愉快地允许使用无效的密钥大小,仅在警告您时(如果您很幸运).当然,这与任何定义良好的AES库都不兼容.

The mcrypt and OpenSSL wrappers will also happily allow invalid key sizes, only warning you - if you're lucky. That's of course not compatible with about any well defined AES library.

这篇关于无法使用AES-256-CBC的pgcrypto解密,但AES-128-CBC可以的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆