Gentoo Wiki


This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc


I set up a mail server according to HOWTO Email Virtual Hosting with Courier and MySQL and wanted to write a little page, to let my users change their passwords, without my intervention. Soon I realised that the standard crypt function does not work out very well. After digging through the source, I found out that you can use the md5, sha1 or sha256 hashing methods, too! I found no resources on this, so I decided to write a tutorial.

Background Information

Courier's authlib, checks wether the encrypted password contains specific characters at the beginning of the string. The following values are known:


"$1$", "{MD5}": MD5
"{SHA}"       : SHA1
"{SHA256}"    : SHA256

Then the base64 encoded binary output of the hashing function is expected.


Here's a small Webinterface (enable the hash and mysqli use-flags for php). Don't forget to change the database connection details and the URL.

Code: Code Title
	function range_check($number, $min, $max) {
		if($number > $max ||  $number < $min)
			return false;
		return true;
	echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" ?>
<html xmlns="" xml:lang="de">
	<title>Change mail password</title>
	<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<h1>Change mail password</h1>
if($_SERVER["HTTPS"]!="on") {
	echo "<p>Please, only open this page using an enryptet connection<br /><a href=\"INSERT_YOUR_ADDRESS_HERE\">INSERT_YOUR_ADDRESS_HERE</a></p>";
} else {
	<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
		<p><label for="mail">E-Mail address:</label><br /><input id="mail" name="mail" type="text"  size="30" maxlength="128" /></p>
		<p><label for="oldpw">Old password:</label><br /><input id="oldpw" name="oldpw" type="password"  size="30" maxlength="128" /></p>
		<p><label for="newpw">New password:</label><br /><input id="newpw" name="newpw" type="password" size="30" maxlength="128" /></p>
		<p><input type="submit" value="Send" /><input type="reset" value="Cancel" /></p>
	} elseif ($_SERVER[REQUEST_METHOD]=="POST") {
		if(key_exists("mail", $_POST) && key_exists("oldpw", $_POST) && key_exists("newpw", $_POST)) {
			$error = false;

			if($error |= !range_check(strlen($_POST["mail"]),1,128))
				echo "<p>The mail address has not been submitted!</p>";
			if($error |= !range_check(strlen($_POST["oldpw"]),1,128))
				echo "<p>The old password hast not been submitted!</p>";
			if($error |= !range_check(strlen($_POST["newpw"]),6,128))
				echo "<p>The new password hast not been submitted or is too short!</p>";

			if(!$error) {
                                // Change to your data
				$mysqli = @ new mysqli("localhost","USER_NAME","PASSWORD","TABLE_NAME");>
				if (mysqli_connect_errno()) {
					echo "<p>The connection to the MYSQL server could not be established. Reason:<br />", mysqli_connect_error(), "</p>";
				} else {
					$mail = $mysqli->real_escape_string($_POST["mail"]);
					$oldpw = "{SHA256}" . base64_encode(hash('sha256',$_POST["oldpw"],true));
					$newpw = "{SHA256}" . base64_encode(hash('sha256',$_POST["newpw"],true));
					$query = "UPDATE `passwd` SET `crypt` = '$newpw' WHERE `id` = '$mail' AND `crypt` = '$oldpw'";
					if (!$mysqli->real_query($query)) {
						echo "<p>Error, couldn't update the database!<br />", $mysqli->error, "</p>";
					} else {
							echo "<p>The password has been successfully changed.</p>";
							echo "<p>No password has been changed.</p>";
		} else {
			echo "<p>Error, not all parameters have been submitted.</p>";
	} else {
		echo "<p>Error, an unknow request method has been used!</p>";
Retrieved from ""

Last modified: Fri, 05 Sep 2008 05:21:00 +0000 Hits: 347