我使用以下 MySQL 查询AES_DECRYPT()
:
SELECT *
FROM data_tbl
WHERE AES_DECRYPT(data_point,'aBcDeF')='data_1';
我已经发现 Postgres 11 中的等价物是decrypt()
(F.25.4. Raw Encryption Functions),查询看起来像这样:
SELECT *
FROM data_tbl
AND decrypt(data_point,'aBcDeF','aes')='data_1';
至少,两者的文档让我相信它们是等价的。
数据从 MySQL 转储并导入 PostgreSQL。
- MySQL 中的
data-point
字段是类型varbinary(255)
,值都显示BLOB
在 MySQL Workbench 中。 - Postgres 中的
data_point
字段是类型bytea
,值都显示[binary data]
在 pgAdmin 中。
我承认,我不确定这些数据类型是否等效。
MySQL 查询工作并根据他的条件查找记录。PostgreSQL 没有,尽管记录在那里。所以它似乎是三件事之一:
- 数据类型 (
varbinary(255)
vsbytea
) 不等价 - 数据不匹配 (
BLOB
vs[binary data]
) 不等价 - 函数 (
AES_DECRYPT
vsdecrypt()
) 不等价
我确实尝试通过首先尝试解密 PostgreSQL 中的值,以查看它的可读格式:
SELECT decrypt(data_point, 'aBcDeF', 'aes')
FROM data_tbl;
但这只是[binary data]
为所有行返回。
然后我遇到了这个答案,使用convert_from
如下:
SELECT convert_from(decrypt(data_point, 'aBcDeF', 'aes'), 'SQL_ASCII')
FROM data_tbl;
但是,我只是收到此错误:
ERROR: invalid byte sequence for encoding "UTF8": 0xcf 0xf5
SQL state: 22021
所以在这一点上,我对如何解决主要问题感到困惑。主要问题是在 PostgreSQL 11 中进行等效AES_DECRYPT
操作。最后一条错误消息不是什么大问题,但它可能与decrypt()
不返回相同的结果有关。
有什么建议么?
实际上,我怀疑您的所有三个假设都是正确的,并且都在您无法解密数据的原因中发挥了作用。我将尝试解释一下。
加密和解密中最重要的因素之一是二进制兼容性——更准确地说,每个数据库如何物理存储数据?数据是大端还是小端存储,内部数据结构是如何实现的(
VARBINARY
和之间的二进制区别BYTEA
是什么),每个系统上使用的字符集和编码是什么?加密是位敏感的,因此位/字节顺序的任何变化都会影响任何加密或解密的结果。此外,即使两个系统都可以使用 AES,它们的默认设置也略有不同。在 MySQL 上,AES 的默认值是使用 ECB 模式的 128 位密钥;而在 PostgreSQL 上,默认是使用 CBC 模式加密数据的 128 位密钥。您将需要确保用于加密/解密的所有选项都是相同的(即使您尝试在同一系统中对其进行解密)。
从逻辑上讲,如果两个系统之间的一切都相同,您应该能够解密数据。在实践中,它会比这更难,如果你可以访问源系统,在那里解密,导出数据,然后在 PostgreSQL 中导入和加密它。
是的,您似乎可以将 pgcrypto
decrypt
与用 mysql 加密的值一起使用aes_encrypt
。例子:
在 PostgreSQL 中:
至于您提到的查看数据的麻烦:
pgAdmin 只显示类型内容的 [二进制数据]
bytea
。如果使用命令行工具
psql
,它将显示内容的十六进制表示(实际上取决于bytea_output
参数,但默认为十六进制)。否则,SQL 函数
encode
可以做到这一点:如果初始(预加密)内容表示一段经过有效编码的文本,请使用
convert_from(binary_string, encoding)
正确的编码。远离SQL_ASCII
:它是一种不代表任何特定编码的伪编码,并且是一种很少有合法用例的hack。就您个人而言,我首先要做的是在解密之前比较 PostgreSQL 和 MySQL 中出现问题的数据行的内容,以验证导出/导入过程。如果它们不匹配,当然它们不会解密为相同的值。