有這類決策的一堆階段,它不只是「推插件進棧和加密的事情是照顧」
首先,你真的需要爲每列分類它對攻擊者的吸引力&什麼搜索/查詢需要使用它,無論是連接列/候選索引等。一些數據需要比其他數據更強大的保護。
考慮一下你要保護對誰:
- 休閒攻擊者(用於遠程表的拷貝,例如SQL注入孔)
- 偷來的數據庫備份(提示:加密這些太)
- 被盜/泄露日誌文件,可能包括查詢和參數
- 帶有直接非超級用戶SQL級別訪問的攻擊者
- 攻擊者直接超級用戶SQL級別的訪問
- 攻擊誰獲得了「Postgres的」 OS用戶直接訪問,這樣他們就可以修改配置,複製/編輯日誌,安裝惡意擴展,改變功能定義等等
- 攻擊誰在數據庫服務器上獲得根
當然,也有應用程序服務器,上游妥協編程語言和工具包的可信源,等等。最終,你達到了一個點,你必須說「我不能切實防禦這一點「。你不能防止有人進來,說:「我來自政府,除非你允許我在這個客戶的服務器上安裝rootkit,否則我會爲你做x/y/z」。關鍵是你必須決定你的做什麼必須防範,並基於此做出安全決策。
一個很好的折衷辦法可能是在應用程序中儘可能多地使用加密,所以PostgreSQL從不會看到加密/解密密鑰。儘可能使用單向散列,而不是使用可逆加密,並且當你散列時,正確地散列你的散列。
這意味着pgcrypto
實際上並沒有太大的好處,因爲您永遠不會向服務器發送純文本,也不會將密鑰材料發送到服務器。
這也意味着對於列SecretValue具有相同明文的兩個人對於數據庫中的SecretValueSalt, SecretValueHashedBytes
具有完全不同的值。所以你不能加入它,在WHERE
子句中有用地使用它,有用地索引它,等等。
出於這個原因,你會經常危及安全。您可以對數據的一部分進行無損哈希,以便獲得部分匹配,然後將所有結果提取到您的應用程序,並在需要完整信息的應用程序端進行過濾。所以您的SecretValue存儲現在看起來像SecretValueFirst10DigitsUnsaltedHash, SecretValueHashSalt, SecretValueHashBytes
。但更好的列名稱。
如果有疑問,只是不要發送對數據庫敏感的任何明文。這意味着pgcrypto
對你來說沒有多大用處,你會主要做應用程序端加密。 #1的原因是,如果您發送明文(或更糟糕的是,密鑰材料)到數據庫,它可能會暴露在日誌文件中,pg_stat_activity
等
您幾乎總是想要存儲加密數據在bytea
列。如果你確實堅持你可以用hex或base64對它進行編碼並將其推到text
列中,但以後需要使用你的系統的開發人員和DBA會哭泣。
每當你考慮加密時,你不能將「如何」與「爲什麼」分開。你的目標是什麼?你試圖保護什麼,從誰那裏*? –
主要目的是在數據庫備份「被盜」或數據庫文件本身從服務器「被盜」的情況下,對這些列具有基本的加密保護。我希望這可以在不增加太多代碼複雜度的情況下實現,同時避免錯誤加密過程無意中破壞數據的風險。 – Soferio