使用 Python 和 PostgreSQL 进行加密

Gar*_*phy 2 python encryption postgresql

我们有一个数据库,其中包含需要加密的个人身份信息 (PII)。

从 Python 方面,我可以使用 PyCrypto 使用 AES-256 和可变盐来加密数据;这会生成 Base64 编码的字符串。

从 PostgreSQL 端,我可以使用 PgCrypto 函数以相同的方式加密数据,但这会产生一个 bytea 值。

对于我的一生,我找不到一种方法在这两者之间进行转换,或者对两者进行比较,以便我可以对加密数据进行查询。有什么建议/想法吗?

注意:是的,我意识到我可以在数据库端进行所有加密/解密,但我的目标是确保应用程序和数据库之间传输的任何数据仍然不包含任何 PII,因为它可以在理论上,很容易被拦截,或者通过日志记录可见。

Cra*_*ger 5

假设您的表中有一个社会安全号码字段。用户必须能够在需要时查询特定的 SSN。显然,SSN 需要加密。我可以从 Python 端对其进行加密并将其保存到数据库中,但为了使其可搜索,我必须对每条记录使用相同的盐,以便我可以将加密值合并到我的 WHERE 子句中,这只会让我们变得脆弱。我可以在数据库端加密/解密,但在这种情况下,每当我查询时,我都会以纯文本形式发送 SSN,这也很糟糕。

此类问题的通常解决方案是存储未加盐或固定盐散列的部分值,以及随机加盐的完整值。您对散列部分值进行索引并对其进行搜索。您将得到误报匹配,但仍然可以从数据库端索引搜索中受益匪浅。您可以获取所有匹配项,并在应用程序端丢弃误报。

查询加密数据就是安全性和性能之间的折衷。没有什么神奇的答案可以让您将哈希值发送到服务器并让它与一堆随机加盐和哈希值进行比较以进行匹配。事实上,这正是我们对哈希值加盐的原因- 以防止其发挥作用,因为这也是攻击者在尝试暴力破解时所做的事情。

所以。妥协。要么以明文形式(通过 SSL)发送 SSN,以便与加盐和散列存储值进行比较,但要知道它仍然大大减少了暴露,因为无法立即转储全部内容。或者索引部分值并对其进行搜索。

请注意,发送未散列值的另一个问题是它们可能会出现在服务器错误日志中。即使您没有log_statement = all,如果出现错误(例如查询取消或死锁中断),它们仍然可能会出现。将值作为查询参数发送会减少它们在日志中出现的位置数量,但远非万无一失。因此,如果您以明文形式发送值,则必须将日志视为安全关键。乐趣!