php - 使用准备好的语句提取 MySQL 信息时使用 AES 进行解密
问题描述
在昨天接受有关尝试对我的用户名进行哈希处理后,我决定使用 MySQL 中的 AES_ENCRYPT 和 DECRYPT 函数来安全地存储我的用户名。就目前而言,我可以使用以下方法对它们进行加密并将它们存储在我的数据库中:
$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$stmt = $con->prepare("INSERT INTO users (username, password) VALUES (AES_ENCRYPT(?, '$aesKey'), ?)");
$stmt->bind_param("ss", $username, $password);
$username = $_POST['username'];
$plainPass = $_POST['password'];
$password = password_hash($plainPass, PASSWORD_ARGON2I);
$stmt->execute();
$stmt->close();
$con->close();
echo "<script> location.href='login.php'; </script>";
}
?>
我正在使用从配置文件加载的 256 位加密密钥,称为$aesKey
但是,当我尝试登录时,我无法登录。什么都没发生。没有打印 SQL 错误,但我确实得到了PHP Notice: Undefined variable: username
. 这是代码:
$submittedUser = $_POST['username'];
$submittedPass = $_POST['password'];
$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if ($stmt = mysqli_prepare($con, "SELECT * FROM users Where username =AES_DECRYPT(?, '$aesKey')")) {
mysqli_stmt_bind_param($stmt, "s", $submittedUser);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
echo mysqli_error($con);
}
while($row = mysqli_fetch_array($result))
{
$username = $row['username'];
$password = $row['password'];
}
if ($submittedUser == $username && password_verify($submittedPass, $password))
{
$_SESSION['user']=$username;
//echo "<script> location.href='index.php'; </script>";
// exit;
}
else
{
//echo "<script> location.href='login.php'; </script>";
// exit;
}
mysqli_close($con);
}
?>
我注释掉了重定向,因为我最初认为它们是导致错误消息不被打印的原因。谁能帮我吗?我似乎无法弄清楚什么不起作用。
编辑:我将语句改回"SELECT * FROM users Where username =AES_ENCRYPT(?, '$aesKey')"
并收到以下输出:
Array ( [0] => 5�uY��V�s~"�ܮ� [username] => 5�uY��V�s~"�ܮ� [1] => $argon2i$v=19$m=1024,t=2,p=2$akcuREppYk1ERjRlUi5ZQw$yIdC5oMblekARArcB0XjwwmWywJ824iM8FmKqAu+9ys [password] => $argon2i$v=19$m=1024,t=2,p=2$akcuREppYk1ERjRlUi5ZQw$yIdC5oMblekARArcB0XjwwmWywJ824iM8FmKqAu+9ys )`
编辑2:这是数据库结构。未加密的用户名应为 evan,未加密的密码应为 edwards。
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`username` text NOT NULL,
`password` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`username`, `password`) VALUES
('5ÇuY¯úVõs~\"ÐÜ®€', '$argon2i$v=19$m=1024,t=2,p=2$NWZQS2Q3dE1ORndjaUdpWg$vOR3DBT+IhdAXIt7YUPDiExalf1lsMeIVe/zTZDDYfU');
编辑 3:运行以下代码:
<?php
include 'config.php';
$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
$result = mysqli_query($con,"SELECT * FROM `users`");
while($row = mysqli_fetch_array($result))
{
echo $row['username'];
echo "<br>";
echo $row['password'];
}
mysqli_close($con);
?>
给我以下结果:
5�uY��V�s~"�ܮ�
$argon2i$v=19$m=1024,t=2,p=2$NWZQS2Q3dE1ORndjaUdpWg$vOR3DBT+IhdAXIt7YUPDiExalf1lsMeIVe/zTZDDYfU
解决方案
为了从数据库中得到你想要的东西,你需要在查询中做两件事,解密的用户名(用于提交的用户名)和与提交的用户名的比较。感谢@msbit 朝着正确的方向开始:
if ($stmt = mysqli_prepare($con, SELECT AES_DECRYPT(username, '$aesKey') FROM users WHERE AES_DECRYPT(username, '$aesKey') = ?){...
第一次解密,SELECT AES_DECRYPT(username, '$aesKey') as username
将为您提供$row['username']
稍后在代码中使用的用户名标识符。
第二个,WHERE AES_DECRYPT(username, '$aesKey') = ?
实际执行解密的用户名与提交的用户名的比较。
编辑
在此处使用 OP 的键和名称(TEXT
作为列类型)是插入语句:
INSERT INTO aes_test (username, encrypted) VALUES ('evan', AES_ENCRYPT('evan', '69552E16F55C3E88CF3CBC44EB5F71B24DD0CF5CB3A7C65EA97BC69224CF42F1'));
这是查询,因为它应该是针对特定用户的:
SELECT username, AES_DECRYPT(`encrypted`, '69552E16F55C3E88CF3CBC44EB5F71B24DD0CF5CB3A7C65EA97BC69224CF42F1') FROM aes_test WHERE AES_DECRYPT(`encrypted`, '69552E16F55C3E88CF3CBC44EB5F71B24DD0CF5CB3A7C65EA97BC69224CF42F1') = 'evan'
结果如下:
埃文 | 埃文
推荐阅读
- node.js - 通过 Angular CLI 创建新的 Angular 项目时出现意外的 json 错误结束
- c - 检查 CS50 哈佛现金应用程序中的 50 错误
- mysql - 在 MySQL 触发器中将值设置为变量
- python - 我想为 imread 目录编号
- json - 调用 JSONDecoder 后,对象没有明显变化
- c# - asp.net - GridView 中的 JSON 格式
- python - 如何将单个字符串与熊猫中的多个字符串进行比较?
- laravel - “非静态方法 Redis::get() 不能被静态调用”在生产中但不是在本地
- javascript - 用对对象字面量的多个赋值替换 switch 语句
- powershell - 无法使用 Start-Process powershell.exe 在 onedrive 路径运行 ps1 文件