如何在 PostgreSQL 中使用 aes 加密?
我使用以下語句嘗試了 aes-encryption:
SELECT encrypt('test', 'key', 'aes');
這有效,但我無法解密該值。我將它插入到數據類型bytea的欄位中,但我不確定這是否是正確的方法。
SELECT decrypt(pw, 'key', 'aes') FROM table WHERE ID = 1;
給我錯誤
錯誤:函式解密(bytea,未知,未知)不存在
第 1 行:從表 WHERE ID = 7 中選擇解密(pw,‘key’,‘aes’);^
提示:沒有函式匹配給定的名稱和參數類型。您可能需要添加顯式類型轉換。
這是否真的意味著 encrypt() 是一個現有函式,而不是 decrypt()?我還能如何檢索 aes 加密的值?
\df *crypt
在 psql 中揭示了 pgcryptoencrypt
和decrypt
函式的參數類型(就像 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 ...
所以
encrypt
和decrypt
函式都期望 key 是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
系統日誌中。IMO 通常最好在應用程序中進行加密。log_statement
見證這個會話,
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
特權的攻擊者的情況下被複製,只是更難正確計時。通過撤銷對frompg_stat_activity
的訪問可以避免攻擊 via ,但這只是表明,除非您知道您的應用程序是唯一可以訪問它的東西,否則最好將您的密鑰發送到數據庫。即使那樣,我也不喜歡。pg_stat_activity``public
如果是密碼,您應該儲存它們嗎?
此外,如果您要儲存密碼,請不要對它們進行雙向加密;如果有所有可能的鹽密碼,則對它們進行雜湊處理並儲存結果。您通常不需要能夠恢復密碼明文,只需確認儲存的雜湊與使用者發送給您登錄的密碼匹配,當它使用相同的鹽進行雜湊處理時。
如果是 auth,讓別人為你做
更好的是,根本不儲存密碼,針對 LDAP、SASL、Active Directory、OAuth 或 OpenID 提供程序或其他一些已經設計和工作的外部系統進行身份驗證。
資源
還有更多。