如何使用pgcrypt在SQLAlchemy中实现列级PostgresSQL加密?

Sof*_*rio 1 postgresql sqlalchemy heroku 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.

一个代码示例和/或一些讨论将是最受欢迎的.

Cra*_*ger 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会哭.