我正在编写一个快速REST服务来管理我们域名的电子邮件帐户,并遇到了一个我无法解释的奇怪行为。
我正在使用mysql来验证电子邮件帐户,我们的REST服务使用Web界面管理maildirs并插入或更新auth凭据。插入用户以及更新密码的查询都使用encrypt
mysql命令。
奇怪的是,在REST界面上更改密码至少一次之前,插入的用户将无法进行身份验证。这意味着encrypt
正在为更新设置正确的值,但插入有问题。
我已尝试在其余服务端的GET / POST参数中记录所有内容,并且似乎数据库层出现问题。 REST服务在两个端口记录密码的params。执行查询时有些不同。
我的查询看起来像这样(在Python中使用MySQLdb):
ADD_USER = "INSERT INTO users (id,name,maildir,crypt) VALUES (%s,%s,%s,encrypt(%s));"
CHANGE_PASS = "UPDATE users SET crypt = encrypt(%s) WHERE id=%s"
同样,ADD_USER
正在输入一个错误的哈希,其中CHANGE_PASS
成功,其中crypt
传递给它们的完全相同的HTTP参数(作为字符串)。有没有理由为什么数据层会进行不同的加密,或者我是在咆哮错误的树?
答案 0 :(得分:1)
首先:如果您能提供帮助,请不要使用ENCRYPT()
作为密码。它有点受限(例如:它忽略了密码的前8个字符以外的所有内容),并且它不是特别安全,特别是因为它意味着MySQL查询记录将记录您的用户'密码!你在Python中做密码散列要好得多 - 这意味着不仅MySQL不必知道任何有关实际密码的信息,而且还允许你使用更强大的密码散列算法。
尽管如此,请记住ENCRYPT()
不是纯哈希函数。除非你传入salt作为第二个参数,否则它的结果不是常数。你是如何检查密码的?一个正确的解决方案看起来像:
SELECT * FROM users WHERE <...> AND crypt = ENCRYPT(%s, crypt) ...
或者,在Python中:
row.crypt == crypt.crypt(users_input_password, row.crypt)
答案 1 :(得分:1)
如果你使用不带盐的加密,它将使用基于当前时间的盐,所以每次你调用它,你会得到一个不同的哈希:
mysql> select encrypt('test');
+-----------------+
| encrypt('test') |
+-----------------+
| 92SErC2PadiaQ |
+-----------------+
mysql> select encrypt('test');
+-----------------+
| encrypt('test') |
+-----------------+
| A2jgxXgOJx7ls |
+-----------------+
前两个字符(在标准情况下)是盐。如果你想检查它,你使用旧密码作为salt,除了前两个字符之外的所有字符都被忽略:
mysql> select encrypt('test', 'A2jgxXgOJx7ls');
+----------------------------------+
| encrypt('test', 'A2jgxXgOJx7ls') |
+----------------------------------+
| A2jgxXgOJx7ls |
+----------------------------------+
如果你想要更强的密码,你必须使用特殊的盐:
mysql> select encrypt('test', '$1$12345678$') as md5;
+------------------------------------+
| md5 |
+------------------------------------+
| $1$12345678$oEitTZYQtRHfNGmsFvTBA/ |
+------------------------------------+
mysql> select encrypt('test', '$5$0123456789abcdef$') sha256;
+-----------------------------------------------------------------+
| sha256 |
+-----------------------------------------------------------------+
| $5$0123456789abcdef$Wm4jf6bGxEoelzY0H/fTvcw8Qcshq0hyLaRfZWtN8q. |
+-----------------------------------------------------------------+
mysql> select encrypt('test', '$6$0123456789abcdef$') as sha512;
+------------------------------------------------------------------------------------------------------------+
| sha512 |
+------------------------------------------------------------------------------------------------------------+
| $6$0123456789abcdef$vNATSYYTivQfXwPTUT4q.sRFLs/sgxDXaPipzRlX3WOO4r1NcR.Og5OoU2Cd2agm1WA3pCJ30JU4EKMxpZaDy/ |
+------------------------------------------------------------------------------------------------------------+
所以这一切都取决于你使用的盐。永远不要使用无盐的哈希。