在sql中遇到密码问题:
以下代码通过随机生成10个字符的字符串来填充特定密码:
Update Teacher
SET TeacherSalt = SUBSTRING(MD5(RAND()), -10),
TeacherPassword = SHA1(CONCAT('009b9b624aaecc4b3217dcd4bfee15ab704745d7',SUBSTRING(MD5(RAND()), -10)))
WHERE TeacherPassword = '009b9b624aaecc4b3217dcd4bfee15ab704745d7'
但我的问题是我想要更改盐,以便它生成的字符串来自所有这些字符:
./ ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
共有63个字符。这样做的php方式如下:
$salt = "";
for ($i = 0; $i < 40; $i++) {
$salt .= substr(
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
mt_rand(0, 63),
1);
}
但是我怎么能用上面的sql方式写这个呢?
答案 0 :(得分:4)
可以在MySQL中完成。随机字生成虽然不是很漂亮。关于产生和应用盐,这部分并不难。
使用2个语句首先为每个人生成盐,然后应用它们。 (注意:如果您真的只想将它应用于一个帐户,那么添加一个WHERE子句。)
mysql> select * from salty;
+------+------+------+
| id | pw | salt |
+------+------+------+
| 1 | fish | NULL |
| 2 | bird | NULL |
| 3 | fish | NULL |
+------+------+------+
(请注意,用户1和3碰巧使用相同的密码。但是一旦盐渍和散列,您不希望它们相同。)
mysql> update salty set salt=SUBSTRING(MD5(RAND()), -10);
mysql> select * from salty;
+------+------+------------+
| id | pw | salt |
+------+------+------------+
| 1 | fish | 00fe747c35 |
| 2 | bird | ee4a049076 |
| 3 | fish | 6a8285f03c |
+------+------+------------+
(注意:我稍后会显示特定的字母表版本)
mysql> update salty set pw=sha1(concat(pw,salt));
mysql> select * from salty;
+------+------------------------------------------+------------+
| id | pw | salt |
+------+------------------------------------------+------------+
| 1 | ac1b74c36b4d2426460562e8710bd467bd034fc8 | 00fe747c35 |
| 2 | d63d035f9cac1ac7c237774613b8b702d8c227df | ee4a049076 |
| 3 | 6a0b1e36f489ef959badf91b3daca87d207fb5de | 6a8285f03c |
+------+------------------------------------------+------------+
你有两个陈述,每一行都有独特的盐渍和散列。
现在,随机生成指定字母的单词,ELT()有一个丑陋的技巧。对于一个64个字母的10个字母的单词:
UPDATE salty SET salt=CONCAT(
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9')
)
mysql> select * from salty;
+------+------+------------+
| id | pw | salt |
+------+------+------------+
| 1 | fish | TzHO0e5I/k |
| 2 | bird | 65xLptoDZ3 |
| 3 | fish | JNok/SfmkG |
+------+------+------------+
丑陋,不是吗?但是在单个MySQL语句中执行此操作可能比在PHP中循环并且每行进行一个(或两个)查询要快得多,尤其是如果必须将其应用于具有数百万条记录的表中;一个丑陋的查询与一次创建数百万个查询。
但正如其他人所说,SHA1真的不再是一个足够好的哈希了。
如果你有很多记录,那么使用像这样的几个MySQL查询来更新所有记录以使用SHA2作为临时解决方案可能是有意义的,然后随着时间的推移将它们单独更新为更强的哈希值使用PHP。当然,您需要一些方法来了解给定记录使用的哈希值。
作为旁注,如果您只更新单行(如您的示例中所示),那么您可以使用MySQL变量临时保存随机生成的字符串足够长的时间来更新该行的两列:
mysql> SET @salt=SUBSTRING(MD5(RAND()), -10); UPDATE salty SET salt=@salt,pw=SHA1(CONCAT(pw,@salt)) WHERE id=2; SET @salt=NULL;
这样,@ salt中的相同值用于设置salt和pw计算。但它不适用于多行的更新(它们都会以相同的盐结束)。
答案 1 :(得分:2)
如果你真的想要随意加盐,那么只能通过使用php生成随机盐并使用该盐加密密码并将盐密钥和密码存储在表的两个字段中来实现。表必须具有salt字段和密码字段。但是,如果您只是想使用mysql进行加密而不是查看http://dev.mysql.com/doc/refman/5.5/en//encryption-functions.html
当我们验证用户的登录凭据时,我们遵循相同的过程,只是这次我们使用数据库中的salt而不是生成新的随机数据。我们向其添加用户提供的密码,运行我们的散列算法,然后将结果与存储在该用户配置文件中的散列进行比较。
How do you securely store a user's password and salt in MySQL?
Where do you store your salt strings?
How insecure is a salted SHA1 compared to a salted SHA512
Salt Generation and open source software
我希望你现在明白了。
答案 2 :(得分:1)
简单地说,在php中解决它。首先从表中获取信息(注意,使用自动递增ID而不是密码 - 这可能不是唯一的 - 来选择你的行)
function makeMeASalt($max=40){
$i = 0;
$salt = "";
$characterList = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
while ($i < $max) {
$salt .= $characterList{mt_rand(0, (strlen($characterList) - 1))};
$i++;
}
return $salt;
}
$hash=crypt($password.makeMeASalt(40))
$query="Update Teacher
SET TeacherSalt = '".$salt."', TeacherPassword = ".$hash."
WHERE TeacherID = '".$teacherid."'";
mysql_query($query) or die(mysql_error())
这也解决了已经提到的问题,即你们的盐在不同领域之间是不一样的!
答案 3 :(得分:0)
我想在适当的时候给予赞扬:上面雷的回答为我的回答提供了所有的见解。在回顾他的回答时,我实现了它,但是我通过使用函数和调用其他函数的函数清理了它的完成方式。这是 Ray 答案的清理版本。 (感谢 Ray 的出色回复!)这也比让 php 生成它快得多。
我创建了两个函数。第一个返回一个随机选择的字符。第二个递归调用第一个来构建任意长度随机生成的字符串(例如在盐胡椒场景中使用等)。第二个被限制为 255 的字符串长度,但是你可以很容易地修改它。您可以将返回的字符更改为您想要的任何有效字符,只需记住计算数组中的数量,从而将 64 更改为您输入的数量。我特意将数组中所有字符的顺序与 Ray 的顺序重新排列,只是为了完全随机化输出。
函数生成在默认情况下被阻止,必须通过脚本(我使用 Dbeaver)在命令行中输入,以便 root 管理员(在数据库上)可以是唯一输入它的人。我选择了这条更安全的路线,而不是像某些人推荐的那样更改我的日志记录,或者尝试在脚本开始时定义函数是由谁生成的。
因为函数定义需要;包含在其中,必须首先将命令行分隔符更改为 $$,然后在输入的函数完成后,将其更改回 ;这只是因为我是通过控制台输入的,而不是我喜欢的工具 (Dbeaver)。
该函数不能使用 DECLARE,必须使用 SET。 SET 变量名前面的@ 是必需的,因为它描绘了我们正在设置用户定义的变量。
现在是功能:
/* Testing Purposes:
SELECT f_generateRandomLetter64();
*/
DROP FUNCTION IF EXISTS f_generateRandomLetter64;
DELIMITER $$
CREATE FUNCTION f_generateRandomLetter64()
RETURNS varchar(1)
CONTAINS SQL
READS SQL DATA
NOT DETERMINISTIC
BEGIN
SET @thisResult = '';
SET @thisResult = ELT(1+FLOOR(RAND()*64),
'/','a','b','c','d','e','f','g','h','i','j','k','P','Q','R','S','T','U','V','W','X','Y','Z',
'.','A','B','C','D','E','F','G','4','8','9','5','6','z','1','2','3','7','l','m','n','o','p',
'q','r','s','H','I','J','K','L','M','N','O','t','u','v','w','x','y','0'
);
RETURN @thisResult;
END $$
DELIMITER ;
下一个函数:
/* Testing Purposes:
SELECT f_generateRandomString(128);
SELECT LENGTH(f_generateRandomString(10));
*/
DROP FUNCTION IF EXISTS f_generateRandomString;
DELIMITER $$
CREATE FUNCTION f_generateRandomString(var_strLength int)
RETURNS varchar(255)
CONTAINS SQL
READS SQL DATA
NOT DETERMINISTIC
BEGIN
SET @thisResult = '';
WHILE var_strLength > 0 DO
SET @thisResult = CONCAT( @thisResult,f_generateRandomLetter64() );
SET var_strLength = var_strLength -1;
END WHILE;
RETURN @thisResult;
END $$
DELIMITER ;