如何使用pgcrypto在SQLAlchemy中实现列级PostgresQL加密?

时间:2014-01-20 02:57:04

标签: postgresql heroku sqlalchemy pgcrypto

例如,在Django中有一个repo:https://sourcegraph.com/github.com/dcwatson/django-pgcrypto

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

我使用SQLAlchemy在Heroku上运行Flask。

非常感谢代码示例和/或一些讨论。

1 个答案:

答案 0 :(得分:5)

这种决策有很多阶段,它不仅仅是“将插件插入堆栈并且加密事情得到了解决”

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

考虑一下您试图保护

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

当然,还有app服务器,上游对编程语言和工具包的可靠来源的妥协等等。最终你达到了一个你必须说“我无法现实地抵御这一点”的地步。你不能防止有人进来,说“我来自政府,除非你允许我在这个客户的服务器上安装rootkit,否则我会向你做x / y / z”。关键是你必须决定你做什么必须防范,并根据这个做出安全决定。

一个很好的折衷方案是在应用程序中尽可能多地执行加密操作,因此PostgreSQL永远不会看到加密/解密密钥。尽可能使用单向散列,而不是使用可逆加密,当您进行散列时,正确地为您的散列加盐

这意味着pgcrypto实际上并没有给你带来太多好处,因为你永远不会向服务器发送明文,也不会向服务器发送密钥材料。

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

出于这个原因,您通常会在安全方面妥协。您可以对部分数据执行未加盐的哈希,以便获得部分匹配,然后将所有结果提取到应用程序,并在应用程序端过滤它们,在那里您可以获得所需的完整信息。因此,您对SecretValue的存储现在看起来像SecretValueFirst10DigitsUnsaltedHash, SecretValueHashSalt, SecretValueHashBytes。但是有了更好的列名。

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

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