鉴于Laravel的Crypt
总是添加盐,因此相同加密的两个实例不相同。
通常,这很好,因为我可以比较两者的解密版本。但是,如果我想搜索在数据库中加密的值,该怎么办?
假设我有users
的表格,我想加密电子邮件地址。现在我想通过电子邮件test@email.com
找到某人。
我该如何为此编写查询?我不能只Crypt::encrypt($email)
进行搜索,因为encrypt
的迭代将与数据库中的迭代不同。
修改
目前,我能想到的唯一一件事就是全力以赴,并通过它们进行过滤:
$match = User::all()->filter(function($record) use($email) {
$field = $record->email['email'];
if(Crypt::decrypt($field) == $email) return $record;
});
但这太可怕了。我不想搜索所有内容。
答案 0 :(得分:2)
如上所述,你不能。如果您不需要优化它,您给出的答案就是实现它的方式。
如果您确实需要优化它,而完全不会破坏加密值,并且已经分析以查找过滤器返回和处理的数据量是导致延迟的主要原因,那么您可以执行以下
向表中添加一个新字段,用于存储哈希的子集。根据唯一电子邮件地址的数量,您可以调整此子集的大小。注意:越小越好,因为您使用此方法泄漏了有关加密值的一些信息。例如,如果您存储电子邮件地址的1字节哈希值,则会将加密的熵减少大约8位。
查询时,首先创建电子邮件哈希的子集,然后放置where
子句以仅返回这些行。
所有这些假设散列函数比解密步骤便宜。如果你想增加它的大小,这种方法需要你重新计算所有哈希子集,所以选择一个有意义地提高性能的大小,不会过度损害加密,很可能不会受到影响。需要随着成长而变化很重要。
注意:在这种情况下,您不应该使用像MD5这样的直接哈希。不是因为它对碰撞的敏感性,而是因为关键空间太小了。如果性能很重要并且存储大量数据,则会打开自己的DOS攻击,攻击者会创建大量电子邮件地址,这些地址都会散列到同一子集。要解决此问题,请使用带有密钥的HMAC函数。
请记住,除非您有真正的性能原因需要增加复杂性 - 不要