Eu tentei a criptografia aes usando a seguinte declaração:
SELECT encrypt('test', 'key', 'aes');
que funcionou, mas não consigo descriptografar o valor. Inseri-o em um campo do tipo de dados bytea mas não tenho certeza se foi o caminho certo.
SELECT decrypt(pw, 'key', 'aes') FROM table WHERE ID = 1;
me dá o erro
ERRO: função decrypt(bytea, desconhecido, desconhecido) não existe
LINHA 1: SELECT decrypt(pw, 'chave', 'aes') FROM tabela WHERE ID = 7; ^
DICA: Nenhuma função corresponde ao nome e aos tipos de argumento fornecidos. Talvez seja necessário adicionar conversões de tipo explícitas.
Isso realmente significa que encrypt() é uma função existente, mas não decrypt()? De que outra forma eu poderia recuperar valores criptografados com aes?
\df *crypt
no psql revela os tipos de argumento do pgcryptoencrypt
edecrypt
funções ( assim como os documentos do PgCrypto ):então ambas as funções
encrypt
edecrypt
esperam que a chave sejabytea
. De acordo com a mensagem de erro, "talvez seja necessário adicionar conversões de tipo explícito".No entanto, funciona bem aqui na página 9.1, então suspeito que há mais do que você mostrou. Talvez você tenha outra função também nomeada
encrypt
com três argumentos?Veja como funciona em um Pg 9.1 limpo:
Uau! Uau! Risco de exposição chave, extrema cautela do administrador necessária!
BTW, por favor, pense cuidadosamente se o PgCrypto é realmente a escolha certa. As chaves em suas consultas podem ser reveladas
pg_stat_activity
e o sistema registra porlog_statement
meio de instruções de criptografia que falham com um erro. IMO é frequentemente melhor fazer criptografia no aplicativo .Testemunhe esta sessão, com
client_min_messages
ativado para que você possa ver o que aparece nos logs:Ops, chave possivelmente exposta nos logs se
log_min_messages
for baixa o suficiente. Agora está no armazenamento do servidor, junto com os dados criptografados. Falhou. Mesmo problemalog_statement
se ocorrer um erro para fazer com que a instrução seja registrada ou possivelmente seauto_explain
estiver habilitada.A exposição via
pg_stat_activity
também é possível. Abra duas sessões e:BEGIN;
LOCK TABLE demo;
select decrypt(pw, 'key', 'aes') from demo;
select * from pg_stat_activity where current_query ILIKE '%decrypt%' AND procpid <> pg_backend_pid();
Opa! Lá vai a chave novamente. Ele pode ser reproduzido sem o
LOCK TABLE
por um invasor sem privilégios, é apenas mais difícil acertar o tempo. O ataque viapg_stat_activity
pode ser evitado revogando o acesso apg_stat_activity
frompublic
, mas serve apenas para mostrar que pode não ser melhor enviar sua chave para o banco de dados, a menos que você saiba que seu aplicativo é a única coisa que o acessa. Mesmo assim, não gosto.Se forem senhas, você deve armazená-las?
Além disso, se você estiver armazenando senhas, não as criptografe bidirecionalmente; se possível , as senhas de sal, então, faça um hash e armazene o resultado . Normalmente, você não precisa recuperar o texto não criptografado da senha, apenas confirme se o hash armazenado corresponde à senha que o usuário envia para você fazer login quando é hash com o mesmo sal.
Se for autenticação, deixe outra pessoa fazer isso por você
Melhor ainda, não armazene a senha, autentique-se em LDAP, SASL, Active Directory, um provedor OAuth ou OpenID ou algum outro sistema externo que já esteja projetado e funcionando.
Recursos
e muito mais.
Após instalar a extensão pgcrypto, para criptografar em AES-256 use:
tipo de campo de resultado é bytea. Armazenado como está no campo do tipo bytea do PostgreSQL. Para descriptografar o bytea:
também campos bytea podem ser codificados/decodificados de/para base64 com funções de codificação/decodificação;