4

I've got a mailserver which stores passwords for mailboxes in a mysql database with the following sql:

ENCRYPT([PASSWORT], concat(_utf8"$1$", right(md5(rand()), 8), _utf8"$"))

But there is no salt stored in the database.

Now i need to build a login process around this database but it is hard to compare the stored password because of the missing salt. I noticed, that the password-hash holds the salt in it self in the following form:

$1$[SALT]$[PASSWORD-HASH]

How can i create a comparable password hash to build a login?

Dovecot is able to login users using the stored passwords but how?

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
  • 1
    `ENCRYPT()` is not a hash. You should use bcrypt or scrypt or PBKDFv2. – SLaks Feb 10 '13 at 18:18
  • Yeah, that might be right and I am going to change taht. But first I need to get deeper into it and understand how it realy works. – user2059250 Feb 10 '13 at 18:25
  • 2
    @SLaks: Actually, [it is](http://dev.mysql.com/doc/refman/5.6/en/encryption-functions.html#function_encrypt). I do agree that the name is horribly misleading. – Ilmari Karonen Feb 10 '13 at 20:05

1 Answers1

5

The MySQL ENCRYPT() function calls the crypt(3) Unix library function, which implements a variety of password hashing algorithms. The specific algorithm to use is selected by the salt parameter, which should begin with an algorithm identifier surrounded by dollar signs; for example, a salt beginning with $1$ corresponds to the old MD5-based hashing scheme by Poul Henning-Kamp.

(The reason for this rather curious way of selecting the algorithm is historical; the original DES-based crypt(3) design from 1976 didn't support alternative hashing algorithms, so a method for designating them had to be shoehorned into the existing interface in order to retain compatibility with old password databases. As it turns out, the resulting system is quite nice and flexible, even if it looks kind of weird at first glance.)

Anyway, all the crypt(3) hashing algorithms (including the original DES-based one) always include the salt (and the algorithm identifier embedded in it) at the beginning of the output, and ignore any extra data appended to the end of the salt input. Thus, to verify a password hash, you simply feed the original hash into ENCRYPT() as the salt, and check if it equals the output:

SELECT user_id,
  password_hash = ENCRYPT('password', password_hash) AS password_is_correct
FROM user_table WHERE user_id = 12345;
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153