支持加密数据库字段的部分字符串匹配的安全方法

Posted

技术标签:

【中文标题】支持加密数据库字段的部分字符串匹配的安全方法【英文标题】:Secure method for supporting partial string matching on an encrypted database field 【发布时间】:2014-04-25 04:48:06 【问题描述】:

我正在编写一个使用 php + mysql 的 Web 应用程序。我知道 PHP 和 MySQL 都可以执行数据加密。我还读到,在安全性方面,更倾向于在 PHP 级别加密数据。但是现在我面临这个问题:我想加密一些用户数据的地址字段。但是在使用PHP编写的网页中,我想支持地址字段的部分字符串匹配。我目前的解决方案是在 MySQL 级别加密数据,然后像这样进行搜索:

// PHP code for inserting data into database
mysql_query("INSERT INTO test VALUES ('', AES_ENCRYPT('" . $addr . "', UNHEX('" . $hexstring . "')))", $link);

// PHP code for partial string matching
mysql_query("SELECT * FROM test WHERE AES_DECRYPT(address, UNHEX('" . $hexstring . "')) like '%Street%'", $link);

有没有更安全的方式在 PHP 级别而不是 MySQL 级别执行加密?我能想到的是检索所有记录,在PHP中解密数据并执行匹配,但它会很慢。 AES不是必须的,任何加密/解密方法都可以,只要足够安全。

【问题讨论】:

我本来打算建议一个部分索引,但是看看你如何在两边都使用通配符,实际上没有索引可以使用。 也许您可以澄清一下您究竟要加密什么值,您的攻击场景是什么以及您想要保护的对象。 @deceze:确实,我不是在寻找能够经受蓄意攻击的解决方案,但我只想找到一个可以加密个人数据的相当安全的解决方案,以便在数据库数据被盗时,人们将无法直接或轻松地读取数据(隐私问题),并且攻击者将无法轻松解密数据。 @LaBird 收获甚微。只要应用程序可以解密数据库,大多数违规行为都能够从应用程序中提取密钥。我宁愿把精力放在访问表面尽可能少的服务器上存储和处理敏感数据。 【参考方案1】:

我想加密一些用户数据的地址字段。但是在使用PHP编写的网页中,我想支持地址字段的部分字符串匹配。

这是加密数据库的难点。您必须在以下两者之间进行选择:

    实验性学术设计(例如顺序显示加密)缺乏我们通常在加密数据时所期望的语义安全性。 使用blind indexes and bloom filters 进行身份验证加密。

如果您更喜欢后一种方法(我喜欢),那么这个过程有点简单:

    为您希望支持的每个部分匹配生成一个单独的密钥。 创建一个函数,将明文确定性地转换为预哈希消息(例如街道编号和道路名称的第一个字母(123 Main Street => 123m 等) 在第 2 步的输出中使用安全的键控散列构造,例如 hash_hmac()hash_pbkdf2()。 (可选):将步骤 3 的输出截断为少量字节(例如 8 个十六进制字符)。这意味着您的搜索结果中会出现更多误报,但可以从获得您的数据库服务器访问权限的对手那里了解到您的明文的唯一区别事实较少。 将其与密文一起存储,密文本身应为encrypted securely。

当然,如果您的加密密钥与数据库服务器存储在同一硬件上,那么所有这些都是徒劳的。能够访问您的数据库(例如 SQL 注入)的攻击者可以逃到文件系统并窃取密钥,除非 Web 服务器和数据库位于不同的硬件上。

【讨论】:

以上是关于支持加密数据库字段的部分字符串匹配的安全方法的主要内容,如果未能解决你的问题,请参考以下文章

哪种 BouncyCastle API 支持的加密算法对于 C# .NET 中的短字符串加密最快且非常安全?

MongoDB:匹配字符串字段中的多个值

关于Nginx根据SNI字段匹配对应证书加密套件支持

11.启信宝数据二次筛选解密(字符串的分割与拼接及正则匹配)-2

利用正则表达式,匹配两字段中间部分

2021 年在 Android 中加密字符串的最佳和最安全的方法是啥?