9
votes

I am working on a web administration module for mailservers (it's open source if you'd like to take a look).

For that, I need to be able to generate hashed password that is readable by Dovecot. As described on their wiki, their recommended password hashing scheme is SSHA256 (the extra S is for salted).

It's also explained that this could be reasonably simple to implement with something like this PHP code:

$salt = 'generate_a_salt_somehow';
$hash = hash('sha256', $password . $salt);

However, from what I've read about cryptography, that is a rather naíve way to generate salted hashes, but if you're doing it wrong when typing A-E-S in your source code, I figured the same could be true in this case.

So if you have insight into cryptography, I'd love to hear about the most secure way to do this, be it mcrypt, mhash or whatever.

2
Oh yeah, and a secure way to make prepare a hash first would also be good :)mikl
Does the hash have to match other implementations? Or is per-site uniqueness acceptable?wallyk
It does have to match Dovecot's implementation to be useful, otherwise users won't be able to log in :)mikl
1) If it's available, I'd use bcrypt. 2) The algorithm shown in the accepted answer is clearly bad (too fast), so you shouldn't use SSHA.CodesInChaos

2 Answers

14
votes

Password generation function in PHP:

$hash = "{SSHA256}".base64_encode(hash('sha256', $password.$salt, true).$salt);

Necessarily "true" - the third parameter...

10
votes

The Dovecot wiki page you linked to explains what the exact hash format Dovecot uses is. You don't have any choice in the matter -- Dovecot has its expectations on what the hash will look like, so you have to play by its rules:

For most of the salted password schemes (SMD5, SSHA*) the salt is stored after the password hash and its length can vary. When hashing the password, append the salt after the plaintext password, e.g.: SSHA256(pass, salt) = SHA256(pass + salt) + salt.

So an appropriate password generation function in PHP might look like:

$hash = "{SSHA256}" . base64_encode(hash('sha256', $password . $salt) . $salt);