简体   繁体   中英

Does mysql encrypt behave differently on INSERT vs UPDATE?

I am working on writing a quick REST service to manage email accounts for our domain and have ran into a strange behavior I can't explain.

I am using mysql to authenticate email accounts, and our REST service manages the maildirs and inserts or updates auth credentials using a web interface. The queries for inserting users as well as updating their passwords both use the encrypt mysql command.

What is strange is that inserted users won't work for authentication until the password is changed on the REST interface at least once. This means that encrypt is setting the right value for an update, but something wrong for an insert.

I have tried logging everything in the GET/POST params on the rest service side and it seems like something is going wrong in the database tier. The REST service logs correct params for passwords at both endpts. Something in the execution of the queries is different.

My queries look like such (using MySQLdb in Python):

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"

Again, ADD_USER is entering a bad hash where CHANGE_PASS succeeds with the exact same HTTP parameters for crypt passed into them (as strings). Is there any reason why the data tier would do different encryption, or am I barking up the wrong tree?

First of all: Don't use ENCRYPT() for passwords if you can help it. It's kind of limited (for instance: it ignores everything beyond the first 8 characters of a password), and it's not particularly secure, especially because it means that MySQL query logging will log your users' passwords! You'd do much better to do password hashing in Python -- this means not only that MySQL doesn't have to know anything about the actual passwords, but also allows you to use stronger password hashing algorithms.

That all being said, keep in mind that ENCRYPT() is not a pure hash function. Its results are not constant unless you pass in a salt as the second argument. How are you checking passwords? A correct solution would look something like:

SELECT * FROM users WHERE <...> AND crypt = ENCRYPT(%s, crypt) ...

Or, in Python:

row.crypt == crypt.crypt(users_input_password, row.crypt)

if you use encrypt without salt, it will use a salt based on the current time, so each time you call it, you'll get a different hash:

mysql> select encrypt('test');
+-----------------+
| encrypt('test') |
+-----------------+
| 92SErC2PadiaQ   |
+-----------------+

mysql> select encrypt('test');
+-----------------+
| encrypt('test') |
+-----------------+
| A2jgxXgOJx7ls   |
+-----------------+

the first two characters (in the standard case) are the salt. if you want to check it, you use the old password as salt, everything but the first two character is ignored:

mysql> select encrypt('test', 'A2jgxXgOJx7ls');
+----------------------------------+
| encrypt('test', 'A2jgxXgOJx7ls') |
+----------------------------------+
| A2jgxXgOJx7ls                    |
+----------------------------------+

if you want stronger passwords, you havet to use a special salt:

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/ |
+------------------------------------------------------------------------------------------------------------+

so it all depends on what salt you use. never use unsalted hashes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM