你最有可能最终做的是有两张桌子。
一个表将包含用户的数据,即唯一的用户 ID、用户名、姓名、电子邮件等。用户名、姓名、电子邮件都将被加密。
第二个表将是一个哈希表。这是您将用来验证用户的用户名和密码的表。它应该具有唯一的用户 ID、用户名的散列(无 IV)值,然后是您将用于password_verify()验证的密码。
当您的用户登录时,他们将提供他们的用户名和密码。用户名将由没有 IV 的同一进程进行散列,以使散列始终等于存储在该用户用户名的散列表中的散列。这将允许您查询相应的记录以检查密码。password_verify()使用该功能检查您的密码。
一旦用户名和密码签出,您已验证您的用户具有适当的凭据,您将使用第一个表上的唯一用户 ID 进行第二次查询。当您的查询返回数据时,它将是该用户的加密值,解密并且您准备好向用户显示用户的信息。
如果我可以访问您的表格,我将永远不会看到您的任何用户信息。我将能够看到唯一用户 id 并看到 id 与两个表上的 id 匹配,但据说所有值都是散列或加密的。
我强烈建议使用Libsodium 库进行散列和加密。(让本地 php 密码函数处理您所有的密码内容。) Libsodium 现在在最新的 PHP 版本上得到本地支持。
建议您的表和服务器的文件目录位于两台物理上不同的机器上。这是因为您将把加密密钥存储在您的目录中,最好是在您的根目录下。如果您的服务器遭到入侵,他们将无法直接访问您的表格,如果您的表格遭到入侵,他们将无法访问您的密钥。
希望这能让你朝着正确的方向前进。
更新
这是一个简单的加密/解密例程,它将在没有 IV 的情况下加密用户名。这意味着只要密钥保持不变,它将每次将相同的纯文本加密为相同的密文。这将允许您根据数据库中的相同密文查询密文。
define("MYKEY_", base64_decode('LoPCPKd8iDxHvb8mATzhhg=='));
function encryptName($plainText) {
return base64_encode(openssl_encrypt($plainText, 'AES-128-CBC', MYKEY_, OPENSSL_RAW_DATA, NULL));
}
function decryptName($cipherText) {
return openssl_decrypt(base64_decode($cipherText), 'AES-128-CBC', MYKEY_, OPENSSL_RAW_DATA, NULL);
}
$text = 'myUserName';
$cipherText = encryptName($text);
echo $cipherText . '<br>';
$plainText = decryptName($cipherText);
echo $plainText;