2

例如,在 Django 中有一个用于执行此操作的存储库:https ://sourcegraph.com/github.com/dcwatson/django-pgcrypto 。

SQLAlchemy 手册中有一些讨论,但我使用的是非字节列:http ://docs.sqlalchemy.org/en/rel_0_9/core/types.html

我正在使用 SQLAlchemy 在 Heroku 上运行 Flask。

代码示例和/或一些讨论将不胜感激。

4

1 回答 1

7

这种决策有很多阶段,不仅仅是“将插件推入堆栈并处理加密的事情”

首先,您确实需要根据其对攻击者的吸引力以及需要使用哪些搜索/查询,是否是连接列/索引候选等来对每一列进行分类。某些数据需要比其他数据更强大的保护。

考虑您要保护的对象

  • 临时攻击者(例如用于远程表副本的 SQL 注入孔)
  • 被盗的数据库备份(提示:也加密这些)
  • 被盗/泄露的日志文件,可能包括查询和参数
  • 具有直接非超级用户 SQL 级别访问权限的攻击者
  • 具有直接超级用户 SQL 级别访问权限的攻击者
  • 直接访问“postgres”操作系统用户的攻击者,因此他们可以修改配置、复制/编辑日志、安装恶意扩展、更改函数定义等
  • 在数据库服务器上获得 root 的攻击者

当然,还有应用程序服务器、编程语言和工具包的可信来源的上游妥协等。最终你不得不说“我无法实际防御这一点”。您无法防止有人进来说“我来自政府,除非您允许我在此客户的服务器上安装 rootkit,否则我会对您做 x/y/z”。关键是你必须决定你必须保护什么,并在此基础上做出你的安全决定。

一个好的折衷办法是在应用程序中尽可能多地进行加密,因此 PostgreSQL 永远不会看到加密/解密密钥。尽可能使用单向散列,而不是使用可逆加密,并且当你散列时,适当地加盐你的散列

这意味着pgcrypto实际上对您没有多大好处,因为您永远不会向服务器发送明文,也不会向服务器发送密钥材料。

这也意味着具有相同明文列 SecretValue 的两个人SecretValueSalt, SecretValueHashedBytes在数据库中具有完全不同的值。所以你不能加入它,在一个WHERE子句中有用地使用它,有用地索引它等等。

因此,您通常会在安全性方面做出妥协。您可能会对部分数据进行未加盐的哈希处理,从而获得部分匹配,然后将所有结果提取到您的应用程序并在您拥有所需全部信息的应用程序端过滤它们。所以你的 SecretValue 存储现在看起来像SecretValueFirst10DigitsUnsaltedHash, SecretValueHashSalt, SecretValueHashBytes. 但是有更好的列名。

如果有疑问,请不要发送任何对数据库敏感的明文。这意味着pgcrypto对您没有多大用处,您将主要进行应用程序端加密。第一个原因是,如果您将纯文本(或更糟糕的是,密钥材料)发送到数据库,它可能会暴露在日志文件pg_stat_activity等中。

您几乎总是希望将加密数据存储在bytea列中。如果你真的坚持你可以对它进行 hex- 或 base64 编码并将它推到一个text列中,但是以后必须使用你的系统的开发人员和 DBA 会哭泣。

于 2014-01-20T13:00:24.163 回答