如何检查包含加密电子邮件地址的表中是否存在电子邮件地址


How to check if an email address exists in a table, which contains encrypted email addresses

我有一个表,其中包含用户的加密电子邮件地址。当一个新用户注册时,我想检查输入的电子邮件地址是否已经存在于表中。我使用php中的openssl_encrypt函数来加密每个电子邮件地址。由于即使传递了相同的字符串作为参数,该函数也会返回不同的加密值,因此我无法检查表中是否已经存在电子邮件地址。加密检查表中是否存在电子邮件地址的可行但安全的方法是什么?

此处回答:在我们关于PHP中的安全数据加密的论文中对加密信息进行索引:

许多公司遇到的一个不常见的问题是,"我们如何加密数据库中的信息,并对其进行索引以快速检索?"例如,如果您需要能够在医疗保健应用程序中通过社会安全号码检索患者记录。

如果您有数百万条记录,那么逐一解密每条记录以执行简单的记录查找对应用程序和数据库服务器来说都是昂贵的。存储这样一个敏感的记录是不可能的(除非你喜欢向客户道歉,并为他们提供一年的免费身份盗窃保护)。

相反,创建此信息的盲索引以用于索引目的。首先,对信息进行加密并将其存储在一个字段中(例如:ssn)。然后,在另一个字段(例如ssn_lookup)中存储具有单独密钥的明文的单独HMAC,并在第二个字段上创建数据库索引。(这个想法是Raul Garcia在MSDN的一篇博客文章中提出的。如果你正在开发一个.NET/SQL Server解决方案来解决这个问题,Raul的博客文章可能更相关。)

用于HMAC索引目的的密钥应该只对需要查询数据库的应用程序服务器可用,该应用程序服务器应该在单独的硬件上,并且永远不要检查到版本控制中。

请注意,这只允许精确搜索,而不允许部分搜索。

public function getAccountByEmail($email)
{
    $search = $this->pdo->prepare("SELECT * FROM table WHERE email_lookup = ?")
        ->execute([
            hash_hmac('sha256', $email, $this->searchKeys['email'])
        ])
        ->fetchAll('PDO::FETCH_ASSOC);
    return $search;
}