Eu tenho esta consulta MySQL usando AES_DECRYPT()
que é o seguinte:
SELECT *
FROM data_tbl
WHERE AES_DECRYPT(data_point,'aBcDeF')='data_1';
Eu descobri que o equivalente no Postgres 11 é decrypt()
(F.25.4. Raw Encryption Functions) e a consulta seria algo assim:
SELECT *
FROM data_tbl
AND decrypt(data_point,'aBcDeF','aes')='data_1';
Pelo menos, a documentação de ambos me leva a acreditar que são equivalentes.
Os dados foram despejados do MySQL e importados para o PostgreSQL.
- O
data-point
campo no MySQL é tipovarbinary(255)
e todos os valores são mostradosBLOB
no MySQL Workbench. - O
data_point
campo no Postgres é tipobytea
e todos os valores são mostrados[binary data]
no pgAdmin.
Se esses tipos de dados são equivalentes, admito, não tenho certeza.
A consulta MySQL funciona e encontra um registro com base nos critérios. O PostgreSQL não, embora o registro esteja lá. Então, parece uma de três coisas:
- Os tipos de dados (
varbinary(255)
vsbytea
) não são equivalentes - Os dados não coincidem (
BLOB
vs[binary data]
) não são equivalentes - As funções (
AES_DECRYPT
vsdecrypt()
) não são equivalentes
Eu tentei descriptografar o valor no PostgreSQL apenas para ver o que está em um formato legível, tentando primeiro:
SELECT decrypt(data_point, 'aBcDeF', 'aes')
FROM data_tbl;
Mas isso acabou de retornar [binary data]
para todas as linhas.
Então me deparei com esta resposta para usar convert_from
como em:
SELECT convert_from(decrypt(data_point, 'aBcDeF', 'aes'), 'SQL_ASCII')
FROM data_tbl;
No entanto, apenas recebo este erro:
ERROR: invalid byte sequence for encoding "UTF8": 0xcf 0xf5
SQL state: 22021
Então, neste ponto, estou perplexo sobre como resolver o problema principal. O principal problema é fazer o equivalente a AES_DECRYPT
mas no PostgreSQL 11. A última mensagem de erro não é tanto um problema, mas provavelmente está relacionada a decrypt()
não retornar os mesmos resultados.
Alguma sugestão?
Na verdade, suspeito que todas as três suposições estão corretas e todas desempenham um papel no motivo pelo qual você não pode descriptografar os dados. Vou tentar explicar um pouco.
Um dos fatores mais importantes na criptografia e descriptografia é a compatibilidade binária - para ser mais preciso, como cada banco de dados armazena fisicamente os dados? Os dados armazenados são big-endian ou little-endian, como as estruturas de dados internas são implementadas (qual é a diferença binária entre
VARBINARY
eBYTEA
), qual é o conjunto de caracteres e a codificação em uso em cada sistema? A criptografia é sensível aos bits e, portanto, quaisquer variações na ordem de bits/bytes afetarão o resultado de qualquer criptografia ou descriptografia.Além disso, embora ambos os sistemas possam usar AES, suas configurações padrão variam um pouco. No MySQL, o padrão para AES é uma chave de 128 bits usando o modo ECB; enquanto no PostgreSQL o padrão é uma chave de 128 bits usando o modo CBC para criptografar os dados. Você precisará garantir que todas as opções usadas para criptografar/descriptografar sejam as mesmas (mesmo se você estivesse tentando descriptografá-lo no mesmo sistema).
Logicamente, se tudo for idêntico entre os dois sistemas, você poderá descriptografar os dados. Na prática, será muito mais difícil do que isso e se você tiver acesso ao sistema de origem, descriptografe lá, exporte os dados, importe e criptografe no PostgreSQL.
Sim, parece que você poderia usar pgcrypto
decrypt
com valores que foram criptografados com mysql'saes_encrypt
.Exemplo:
No PostgreSQL:
Quanto ao problema que você mencionou ao ver os dados:
O pgAdmin apenas exibe [dados binários] para conteúdos do tipo
bytea
.Se estiver usando a ferramenta de linha de comando
psql
, ela exibirá uma representação hexadecimal do conteúdo (na verdade, depende dobytea_output
parâmetro, mas é hexadecimal por padrão).Caso contrário, a função SQL
encode
pode fazer isso:Se o conteúdo inicial (pré-criptografia) representar um pedaço de texto codificado de forma válida, use
convert_from(binary_string, encoding)
com a codificação correta. Fique longe deSQL_ASCII
: é uma pseudo-codificação que não representa nenhuma codificação específica e um hack com muito poucos casos de uso legítimos.Pessoalmente, o que eu faria primeiro no seu caso é comparar o conteúdo das linhas de dados que exibem o problema no PostgreSQL vs MySQL antes da descriptografia, para validar o procedimento de exportação/importação. Se eles não corresponderem, é claro que eles não serão descriptografados com os mesmos valores.