(Nota:não sou especialista em segurança. Tenho interesse na área, mas é isso. Tenha isso em mente.)
Se possível, não armazene senhas
Depende muito de quais são suas necessidades. A melhor opção de todas é não usar criptografia bidirecional; se você puder armazenar apenas salted e one-way-hash senha digere isso é o ideal. Você ainda pode testá-los para ver se eles correspondem a uma senha fornecida pelo usuário, mas nunca a armazena.
Melhor ainda, se seus clientes usam algum protocolo sensato (ou seja:não HTTP como comumente implementado), você pode usar um mecanismo de autenticação de desafio-resposta isso significa que seu aplicativo nunca nunca precisa ver a senha do usuário, nem mesmo ao autenticá-lo. Infelizmente, isso raramente é possível na web pública, que tem segurança que envergonharia os programadores dos anos 80.
Se você precisar armazenar a senha, isole as chaves do aplicativo
Se você deve ser capaz de descriptografar as senhas, idealmente você não deve ter todos os detalhes para fazê-lo em um só lugar, e certamente não em um lugar copiável e facilmente acessível.
Por essa razão, eu pessoalmente prefiro não usar o PgCrypto (como você está fazendo) para esse propósito, porque força você a revelar a chave privada e (se houver) a senha para o servidor, onde ela pode ser exposta no PostgreSQL. arquivos de log ou de outra forma potencialmente farejados. Eu gostaria de fazer minha criptografia do lado do cliente, onde eu pudesse usar o PKCS#11, um agente de chave ou outras ferramentas que me permitissem descriptografar os dados sem nunca ter meu código capaz de acessar a chave.
O problema do armazenamento seguro de chaves faz parte do que PKCS#11 foi inventado para. Ele fornece uma interface genérica para aplicativos e provedores de criptografia para conversar com qualquer coisa que possa fornecer determinados serviços de assinatura e descriptografia sem nunca revelar sua chave . O uso usual, mas não apenas, é com criptografia baseada em hardware, como cartões inteligentes e módulos de criptografia de hardware. Esses dispositivos podem ser instruídos a assinar ou descriptografar os dados passados a eles e podem fazê-lo sem nunca revelar a chave. Se possível, considere usar um smartcard ou HSM. Até onde eu sei, o PgCrypto não pode usar PKCS#11 ou outros HSMs/smartcards.
Se você não puder fazer isso, provavelmente ainda poderá usar um agente de gerenciamento de chaves, onde você carrega sua chave em um programa de gerenciamento de chaves manualmente quando o servidor inicializa e o programa de gerenciamento de chaves fornece uma interface PKCS#11 (ou alguma outra) para assinatura e descriptografia por meio de um soquete. Dessa forma, seu aplicativo da Web nunca precisa saber a chave.
gpg-agent
podem se qualificar para este fim. Novamente, até onde eu sei, o PgCrypto não pode usar um agente de gerenciamento de chaves, embora seja um ótimo recurso a ser adicionado. Mesmo uma pequena melhoria pode ajudar. É melhor que a senha da sua chave não esteja armazenada no disco, então você pode exigir que ela seja inserida quando o aplicativo for iniciado para que a chave possa ser descriptografada. Você ainda está armazenando a chave descriptografada na memória, mas todos os detalhes para descriptografá-la não estão mais no disco e são fáceis de acessar. É muito mais difícil para um invasor roubar a chave descriptografada da memória do que pegar um "password.txt" do disco.
O que você escolhe fazer depende muito dos detalhes de suas necessidades de segurança e dos dados com os quais está trabalhando. Na sua posição, eu simplesmente não armazenaria as senhas, se possível, e, se fosse necessário, usaria um dispositivo de hardware compatível com PKCS#11.