我可以存储散列的 phone 号码并将其未散列发送到电子邮件吗?

Can I store hashed phone number and send it unhashed to email?

我的新 PHP 工作有一个任务,但我不知道是否可以解决。任务:

You need to create PHP web page that implements functional on picture below. Data must be stored in SQL. Hacker can not see user phone numbers and emails even if he got access to database or files. The solutions must contain standard PHP libs.

那么,我应该用什么算法来解决问题呢?我可以使用 password_hash() 函数存储电子邮件,当我需要从电子邮件中检索 phone 号码时,我将使用 password_verify() 来查找电子邮件是否存在。但是如何使用 phone 号码,如果我需要发送纯净且未散列的号码?

PHP 提供内置的 solutions for encrypting and decrypting data. Use e.g. MCrypt, supports a good buffet of common algorithms. What exact cipher you choose is up to you, depending on the level of security required. Read up at Wikipedia on block ciphers for the general picture. Edit: Just learned that MCrypt is deprecated in PHP 7.1 and the use of OpenSSL 被推荐在其位置。

如果即使黑客获得了对您系统的完全访问权限,phone 号码也必须无法访问,那么解密密钥显然必须在服务器外,即。你不能将它存储在数据库或文件系统中。

在您的规范中,此密钥将是与 phone 号码匹配的电子邮件地址。然后,在输入时,您将单向散列电子邮件,并使用未散列的电子邮件作为加密 phone 号码的密钥。在请求时,您将使用电子邮件哈希找到匹配的 phone 号码,并使用未哈希的电子邮件作为密钥对其进行解密。应该让你排序。


更新: 获取与数据库中的 phone/email 对匹配的记录时,如果您使用了 password_hash() (生成新的盐和一个唯一的字符串),那么你唯一的选择就是获取所有记录并通过 password_verify() 迭代它们。这不是特别可扩展。

除非这是一项安全练习,否则我不确定我是否愿意为电子邮件创建一个简单的 sha1() 散列。或者使用例如crypt($email, 'y$Some22CharsOfFixedSalt$'); -- 参见 crypt() -- 并生成一个基于河豚的散列,它使用固定的盐字符串,从而产生一个不变的散列。然后我还会从数据库条目中截断结果字符串的前导盐部分。

如果你觉得自己很狡猾,为什么不设计一个算法从每封电子邮件中派生出一个唯一的字符串,然后在你的哈希函数中使用它作为盐,而不是使用相同的盐来哈希所有电子邮件.

您还可以委托数据库的电子邮件散列并使用 MySQL's encryption functions。然后你会使用例如SHA2('email', 256) 在您的 INSERTSELECT 查询中,像这样:INSERT INTO records VALUES (SHA2('email@what', 256), 'TheEncryptedTelNo');SELECT * FROM records WHERE email = SHA2('email@what', 256);。 (请务必注意手册中关于可能存储在日志中的明文数据的警告;即在执行此操作之前了解您的 MySQL 设置。)