\df *crypt
在psql中显示了pgcrypto encrypt
和decrypt
函数的参数类型(与PgCrypto docs一样):
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
...
因此encrypt
和decrypt
功能都希望键是bytea
。根据错误消息,“您可能需要添加显式类型强制转换”。
但是,它在Pg 9.1上可以正常工作,因此我怀疑它的功能超出了您的显示。也许您还有另一个函数也被命名为encrypt
用三个参数函数?
这是在干净的Pg 9.1上的工作方式:
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)
天啊!天啊!关键暴露风险,需要管理员特别注意!
顺便说一句,请仔细考虑PgCrypto是否真的是正确的选择。您查询中的键可以显示出来,pg_stat_activity
系统可以通过log_statement
或通过密码错误失败的加密语句来记录系统日志。IMO最好在应用程序中进行加密。
见证此会话并client_min_messages
启用它,以便您可以看到日志中显示的内容:
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)
糟糕,如果密钥log_min_messages
足够低,可能会在日志中暴露出来。现在,它连同加密的数据一起存储在服务器的存储中。失败。相同的问题,而不会log_statement
发生错误导致语句被记录或可能auto_explain
已启用。
pg_stat_activity
也可以通过进行曝光。.打开两个会话,然后:
- 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();
哎呀!钥匙又来了。没有LOCK TABLE
特权的攻击者就可以复制它,但是很难正确地定时它。通过攻击pg_stat_activity
可以通过撤销访问要避免pg_stat_activity
从public
,但这只是表明,除非您知道自己的应用程序是唯一访问它的方法,否则最好将密钥发送给数据库。即使那样,我也不喜欢。
如果是密码,应该完全存储吗?
此外,如果要存储密码,请不要对密码进行双向加密;如果可能的盐密码都散列并存储结果。通常,您不需要恢复明文密码,只需确认存储的哈希值与用户发送给您的密码(用相同的盐进行哈希处理)登录时相匹配即可。
如果是授权,请让其他人为您完成
甚至更好的是,根本不存储密码,无需通过LDAP,SASL,Active Directory,OAuth或OpenID提供程序或已经设计并运行的某些其他外部系统进行身份验证。
资源资源
还有更多。