鉴于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;
         });

但这太糟糕了。我不想搜索所有内容。

最佳答案

如前所述,您不能。您给出的答案是不需要优化它的实现方式。

如果确实需要在不完全破坏加密值的情况下对其进行优化,并且已进行概要分析以查找过滤器返回和处理的数据量是造成延迟的主要原因,则可以执行以下操作。

在表中添加一个新字段,该字段将存储哈希的一个子集。根据唯一电子邮件地址的数量,您可以调整此子集的大小。注意:越小越好,因为您正在使用这种方法泄漏有关加密值的某些信息。例如,如果存储电子邮件地址的1字节哈希,则将加密的熵降低了约8位。

查询时,首先创建电子邮件哈希的子集,并放置where子句以仅返回那些行。

所有这些都假定哈希函数比解密步骤便宜。如果要增加散列子集的大小,此方法将要求您重新计算所有散列子集,因此,选择一个能够显着提高性能的大小,不会过度损害加密,并且随着您的成长,很有可能不需要进行更改,这一点很重要。 。

注意:在这种情况下,您不应使用像MD5这样的直接哈希。不是因为它容易受到碰撞的影响,而是因为键空间会很小。如果性能很重要并且您存储大量数据,则可以自己打开DOS攻击,从而使攻击者创建大量电子邮件地址,这些电子邮件地址全部散列到同一子集。要解决此问题,请使用带有 key 的HMAC函数。

请记住,除非出于真正的性能原因需要增加复杂性-否则

10-05 21:15
查看更多