2017-04-21 146 views
1

我在pgcrypto中解密之前曾在PHP應用程序中加密的數據時遇到問題。無法使用AES-256-CBC中的pgcrypto進行解密,但AES-128-CBC無問題

我試圖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 + xXZf6MyPDpQzPZAI6XJQYmwyNUVzKzdaVnNickc5dEg5MUd1anpBYlpLeW9SQjhpZ29yQzRpWFk9」
  • 解密字符串的base64 =「dGVzdA ==」

在這裏,我如何我試圖解密使用相同的密鑰和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解密OK。 在Postgres僅第一(mcrypt aes128cbc)解密好 - 前16個字節仍然是IV,但我可以刪除它們並轉換爲文本。 另外兩個人(mcrypte AES256CBC和openssl256cbc)甚至不像他們被解密。 我評論塊與openssl256cbc,因爲它給我「[39000]錯誤:decrypt_iv錯誤:數據不是塊大小的倍數」錯誤。

任何幫助將不勝感激。

回答

2

MCRYPT_RIJNDAEL_256不是AES-256。它是塊大小爲256的Rijndael密碼(因此是錯誤)。 AES是Rijndael密碼的一個子集,使用塊大小爲128和的密鑰大小爲128,192和256位。這也體現在IV尺寸上。

要創建AES-256加密密文,您可以使用MCRYPT_RIJNDAEL_128並使用正確的密鑰大小(256位是32字節)。


請注意,mcrypt - 特別是底層的C庫 - 不再被維護。你最好使用openssl或更高版本的加密庫。