Skip to content

Commit

Permalink
merge sha512.b64 encrypt support - see postfixadmin#58
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidGoodwin committed Mar 14, 2020
1 parent 48e236f commit 3b9d8f8
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions config.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ function language_hook($PALANG, $language) {
// - don't use dovecot:* methods that include the username in the hash - you won't be able to login to PostfixAdmin in this case
// - you'll need at least dovecot 2.1 for salted passwords ('doveadm pw' 2.0.x doesn't support the '-t' option)
// - dovecot 2.0.0 - 2.0.7 is not supported
// sha512.b64 - {SHA512-CRYPT.B64} (base64 encoded sha512) (no dovecot dependency; should support migration from md5crypt)
$CONF['encrypt'] = 'md5crypt';

// In what flavor should courier-authlib style passwords be encrypted?
Expand Down
31 changes: 31 additions & 0 deletions functions.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,8 @@ function pacrypt($pw, $pw_db="") {
return _pacrypt_mysql_encrypt($pw, $pw_db);
case 'authlib':
return _pacrypt_authlib($pw, $pw_db);
case 'sha512.b64':
return _pacrypt_sha512_b64($pw, $pw_db);
}

if (preg_match("/^dovecot:/", $CONF['encrypt'])) {
Expand All @@ -1245,6 +1247,35 @@ function pacrypt($pw, $pw_db="") {
throw new Exception('unknown/invalid $CONF["encrypt"] setting: ' . $CONF['encrypt']);
}

/**
* @see https://github.com/postfixadmin/postfixadmin/issues/58
*/
function _pacrypt_sha512_b64($pw, $pw_db="") {
if (!function_exists('random_bytes') || !function_exists('crypt') || !defined('CRYPT_SHA512') || !function_exists('mb_substr')) {
throw new Exception("sha512.b64 not supported!");
}
if (!$pw_db) {
$salt = mb_substr(rtrim(base64_encode(random_bytes(16)),'='),0,16,'8bit');
return '{SHA512-CRYPT.B64}'.base64_encode(crypt($pw,'$6$'.$salt));
}


$password="#Thepasswordcannotbeverified";
if (strncmp($pw_db,'{SHA512-CRYPT.B64}',18)==0) {
$dcpwd = base64_decode(mb_substr($pw_db,18,NULL,'8bit'),true);
if ($dcpwd !== false && !empty($dcpwd) && strncmp($dcpwd,'$6$',3)==0) {
$password = '{SHA512-CRYPT.B64}'.base64_encode(crypt($pw,$dcpwd));
}
}
elseif (strncmp($pw_db,'{MD5-CRYPT}',11)==0) {
$dcpwd = mb_substr($pw_db,11,NULL,'8bit');
if (!empty($dcpwd) && strncmp($dcpwd,'$1$',3)==0) {
$password = '{MD5-CRYPT}'.crypt($pw,$dcpwd);
}
}
return $password;
}

/**
* Creates MD5 based crypt formatted password.
* If salt is not provided we generate one.
Expand Down
25 changes: 25 additions & 0 deletions tests/PacryptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,29 @@ public function testPhpCryptRandomString() {
// not impossible though.
$this->assertFalse( strcmp($str1, $str2) == 0 && strcmp($str1, $str3) == 0 );
}

public function testSha512B64() {
$str1 = _pacrypt_sha512_b64('test', '');
$str2 = _pacrypt_sha512_b64('test', '');

$this->assertNotEmpty($str1);
$this->assertNotEmpty($str2);
$this->assertNotEquals($str1, $str2); // should have different salts


$actualHash = '{SHA512-CRYPT.B64}JDYkM2NWcFM1WFNlUHl5MzdwSiRZWW80d0FmeWg5MXpxcS4uY3dtYUR1Y1RodTJGTDY1NHpXNUNvRU0wT3hXVFFzZkxIZ1JJSTZmT281OVpDUWJOTTF2L0JXajloME0vVjJNbENNMUdwLg==';

$check = _pacrypt_sha512_b64('test', $actualHash);

$this->assertTrue(hash_equals($check, $actualHash));

$str3 = _pacrypt_sha512_b64('foo', '');

$this->assertNotEmpty($str3);

$this->assertFalse(hash_equals('test', $str3));

$this->assertTrue(hash_equals(_pacrypt_sha512_b64('foo',$str3), $str3));

}
}

0 comments on commit 3b9d8f8

Please sign in to comment.