我在解密以前在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
2)mcrypt-RIJNDAEL 256 CBC
3)openssl_encrypt-aes-256-cbc
在这里,我如何尝试使用相同的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大小上。
MCRYPT_RIJNDAEL_256
要创建AES-256加密密文,可以使用MCRYPT_RIJNDAEL_128正确的密钥大小(256位为32字节)。的_128后缀指示要使用的块大小; 您仍然可以将其与128、192或256位的任何有效密钥大小一起使用。
MCRYPT_RIJNDAEL_128
_128
请注意,不再维护mcrypt-尤其是基础C库。您最好使用openssl或更高版本的加密库。
mcrypt和OpenSSL包装器也将愉快地允许使用无效的密钥大小,仅在警告您时(如果您很幸运)。当然,这与任何定义良好的AES库都不兼容。