\df *cryptdans psql révèle les types d'arguments de pgcrypto encryptet des decryptfonctions ( comme le font les documents PgCrypto ):
                                List of functions
 Schema |      Name       | Result data type |   Argument data types    |  Type  
--------+-----------------+------------------+--------------------------+--------
 ...
 public | decrypt         | bytea            | bytea, bytea, text       | normal
 public | encrypt         | bytea            | bytea, bytea, text       | normal
 ...
les fonctions encryptet decrypts'attendent donc à ce que la clé soit bytea. Selon le message d'erreur, "vous devrez peut-être ajouter des transtypages de type explicites".
Cependant, cela fonctionne bien ici sur Pg 9.1, donc je soupçonne qu'il y a plus que ce que vous avez montré. Peut-être avez-vous une autre fonction également nommée encryptavec trois arguments?
Voici comment cela fonctionne sur une Pg 9.1 propre:
regress=# create table demo(pw bytea);
CREATE TABLE
regress=# insert into demo(pw) values ( encrypt( 'data', 'key', 'aes') );
INSERT 0 1
regress=# select decrypt(pw, 'key', 'aes') FROM demo;
  decrypt   
------------
 \x64617461
(1 row)
regress=# select convert_from(decrypt(pw, 'key', 'aes'), 'utf-8') FROM demo;
 convert_from 
--------------
 data
(1 row)
Awooga! Awooga! Risque d'exposition clé, extrême prudence administrative requise!
BTW, réfléchissez bien si PgCrypto est vraiment le bon choix. Les clés de vos requêtes peuvent être révélées dans pg_stat_activityet le système se connecte via log_statementou via des instructions de chiffrement qui échouent avec une erreur. OMI, il est souvent préférable de faire de la cryptographie dans l'application .
Soyez témoin de cette session, avec client_min_messagesactivé afin que vous puissiez voir ce qui apparaîtrait dans les journaux:
regress# SET client_min_messages = 'DEBUG'; SET log_statement = 'all'; 
regress=# select decrypt(pw, 'key', 'aes') from demo;
LOG:  statement: select decrypt(pw, 'key', 'aes') from demo;
LOG:  duration: 0.710 ms
  decrypt   
------------
 \x64617461
(1 row)
Oups, la clé peut être exposée dans les journaux si elle log_min_messagesest suffisamment basse. Il est maintenant sur le stockage du serveur, avec les données chiffrées. Échouer. Même problème sans log_statementsi une erreur se produit pour provoquer la consignation de l'instruction, ou éventuellement si elle auto_explainest activée.
Une exposition via pg_stat_activityest également possible. Ouvrez deux sessions et:
- S1: 
BEGIN; 
- S1: 
LOCK TABLE demo; 
- S2: 
select decrypt(pw, 'key', 'aes') from demo; 
- S1: 
select * from pg_stat_activity where current_query ILIKE '%decrypt%' AND procpid <> pg_backend_pid(); 
Oups! Voilà à nouveau la clé. Il peut être reproduit sans LOCK TABLEpar un attaquant non privilégié, il est juste plus difficile de bien le chronométrer. L'attaque via pg_stat_activitypeut être évitée en révoquant l'accès à pg_stat_activityfrom public, mais cela montre simplement qu'il n'est peut-être pas préférable d'envoyer votre clé à la base de données sauf si vous savez que votre application est la seule chose qui y accède. Même alors, je n'aime pas.
S'il s'agit de mots de passe, devriez-vous les stocker du tout?
De plus, si vous stockez des mots de passe, ne les cryptez pas dans les deux sens; si tous les mots de passe possibles sont salés, hachez-les et stockez le résultat . Vous n'avez généralement pas besoin de pouvoir récupérer le mot de passe en clair, confirmez seulement que le hachage stocké correspond au mot de passe que l'utilisateur vous envoie pour vous connecter lorsqu'il est haché avec le même sel.
Si c'est auth, laissez quelqu'un d'autre le faire pour vous
Encore mieux, ne stockez pas du tout le mot de passe, authentifiez-vous contre LDAP, SASL, Active Directory, un fournisseur OAuth ou OpenID ou tout autre système externe déjà conçu et fonctionnel.
Ressources
et beaucoup plus.