簡體   English   中英

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

[英]Can't decrypt using pgcrypto from AES-256-CBC but AES-128-CBC is OK

我在解密以前在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 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

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

3)openssl_encrypt-aes-256-cbc

  • 鍵=“ 85f2669023b98a62d1312af75994ddf1”
  • 初始向量base64 =“ tOi + xXZf6MyPDpQzPZAI6Q ==”
  • 加密的字符串base64 =“ tOi + xXZf6MyPDpQQPZAI6XJQYmwyNUVzKzdaVnNickc5dEg5MUd1anpBYlpLeW9SQjhpZ29yQzRpWFk9”
  • 解密的字符串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'
    )

如您所見,PHP中的所有3個都已解密。 在Postgres中,只有首先解密(mcrypt aes128cbc)正常 -前16個字節仍為IV,但我可以將其刪除並轉換為文本。 另外兩個(mcrypte AES256CBC和openssl256cbc)甚至看起來都不像被解密了。 我用openssl256cbc注釋了塊,因為它給了我“ [39000]錯誤: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庫都不兼容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM