diff --git a/support/schema/aur-schema.sql b/support/schema/aur-schema.sql
index 250d405..f12c57d 100644
--- a/support/schema/aur-schema.sql
+++ b/support/schema/aur-schema.sql
@@ -25,8 +25,8 @@ CREATE TABLE Users (
 	Suspended TINYINT UNSIGNED NOT NULL DEFAULT 0,
 	Username CHAR(32) NOT NULL,
 	Email CHAR(64) NOT NULL,
-	Passwd CHAR(32) NOT NULL,
-	Salt CHAR(32) NOT NULL DEFAULT '',
+	Passwd CHAR(128) NOT NULL,
+	Salt CHAR(32),
 	ResetKey CHAR(32) NOT NULL DEFAULT '',
 	RealName CHAR(64) NOT NULL DEFAULT '',
 	LangPreference CHAR(5) NOT NULL DEFAULT 'en',
diff --git a/web/README b/web/README
index 041b521..f3c1f60 100644
--- a/web/README
+++ b/web/README
@@ -44,6 +44,8 @@ Setup on Arch Linux:
 
    If those php extensions are separate packages on your system, install
    them.
+   The hash extension is usually statically compiled into php. If it is
+   provided as an extension, add it too.
 
    AUR requires PEAR and the File_Find module.
    Installing PEAR will vary depending on the system and may already
diff --git a/web/lib/acctfuncs.inc b/web/lib/acctfuncs.inc
index 9c172bb..d87d5e6 100644
--- a/web/lib/acctfuncs.inc
+++ b/web/lib/acctfuncs.inc
@@ -601,25 +601,19 @@ function display_account_info($U="", $T="", $E="", $R="", $I="") {
  * SID of 0 means login failed.
  */
 function try_login() {
-	$login_error = "";
+	$login_error = "Missing username or password.";
 	$new_sid = "";
 	$userID = null;
 
-	if ( isset($_REQUEST['user']) || isset($_REQUEST['passwd']) ) {
+	if ( isset($_REQUEST['user']) && isset($_POST['passwd']) ) {
+		list($userID, $login_error) = valid_user_passwd($_REQUEST['user'], $_REQUEST['passwd']);
 
-		$userID = valid_user($_REQUEST['user']);
-
-		if ( user_suspended( $userID ) ) {
-			$login_error = "Account Suspended.";
-		}
-		elseif ( $userID && isset($_REQUEST['passwd'])
-		  && valid_passwd($userID, $_REQUEST['passwd']) ) {
+		if ( isset($userID) ) {
 
 			$logged_in = 0;
 			$num_tries = 0;
 
 			# Account looks good.  Generate a SID and store it.
-
 			$dbh = db_connect();
 			while (!$logged_in && $num_tries < 5) {
 				$new_sid = new_sid();
@@ -699,28 +693,6 @@ function valid_username( $user )
 	return;
 }
 
-/*
- * Checks if the username is valid and if it exists in the database
- * Returns the username ID or nothing
- */
-function valid_user( $user )
-{
-	/*	if ( $user = valid_username($user) ) { */
-	if ( $user ) {
-		$dbh = db_connect();
-		$q = "SELECT ID FROM Users WHERE Username = '"
-			. mysql_real_escape_string($user). "'";
-
-		$result = mysql_fetch_row(db_query($q, $dbh));
-
-		# Is the username in the database?
-		if ($result[0]) {
-			return $result[0];
-		}
-	}
-	return;
-}
-
 function good_passwd( $passwd )
 {
 	if ( strlen($passwd) >= PASSWD_MIN_LEN ) {
@@ -729,58 +701,33 @@ function good_passwd( $passwd )
 	return false;
 }
 
-/* Verifies that the password is correct for the userID specified.
- * Returns true or false
+/* Verifies that for the user name specified the user exists, the 
+ * password is correct and it is not suspended.
+ * Returns userid and error message
  */
-function valid_passwd( $userID, $passwd )
+function valid_user_passwd( $userName, $passwd )
 {
 	if ( strlen($passwd) > 0 ) {
 		$dbh = db_connect();
-
-		# get salt for this user
-		$salt = get_salt($userID);
-		if ($salt) {
-			# use salt
-			$passwd_q = "SELECT ID FROM Users" .
-				" WHERE ID = '$userID' AND Passwd = '" .
-				salted_hash($passwd, $salt) . "'";
-			$passwd_result = mysql_fetch_row(db_query($passwd_q, $dbh));
-			if ($passwd_result[0]) {
-				return true;
-			}
-		} else {
-			# check without salt
-			$nosalt_q = "SELECT ID FROM Users".
-				" WHERE ID = '$userID'" .
-				" AND Passwd = '" . md5($passwd) . "'";
-			$nosalt_result = mysql_fetch_row(db_query($nosalt_q, $dbh));
-			if ($nosalt_result[0]) {
-				# password correct, but salt it first
-				if (!save_salt($userID, $passwd)) {
-					trigger_error("Unable to salt user's password;" .
-						" ID $userID", E_USER_WARNING);
-					return false;
-				}
-
-				return true;
-			}
+		
+		$query = "SELECT ID, Suspended, Passwd, Salt FROM Users" .
+			" WHERE Username = '" . mysql_real_escape_string($userName, $dbh) . "'";
+			
+		$result = mysql_fetch_row(db_query($query, $dbh));
+		if (!mysql_num_rows($dbh)) {
+			return array(null, "User doesn't exist.");
 		}
+		
+		if ($result[1])
+			return array(null, "Account Suspended.");
+		
+		if ( salted_hash($passwd, $result[3]) == $result[2] ) {
+			return array($result[0], "Login successful");
+		}
+		return array(null, "Wrong password.");
 	}
-	return false;
-}
-
-/*
- * Is the user account suspended?
- */
-function user_suspended( $id )
-{
-	$dbh = db_connect();
-	$q = "SELECT Suspended FROM Users WHERE ID = '$id'";
-	$result = mysql_fetch_row(db_query($q, $dbh));
-	if ($result[0] == 1 ) {
-		return true;
-	}
-	return false;
+	
+	return array(null, "Wrong password.");
 }
 
 /*
diff --git a/web/lib/aur.inc b/web/lib/aur.inc
index 8ccce89..8f8d469 100644
--- a/web/lib/aur.inc
+++ b/web/lib/aur.inc
@@ -456,33 +456,15 @@ function mkurl($append) {
 	return substr($out, 5);
 }
 
-function get_salt($user_id)
-{
-	$dbh = db_connect();
-	$salt_q = "SELECT Salt FROM Users WHERE ID = '$user_id'";
-	$salt_result = mysql_fetch_row(db_query($salt_q, $dbh));
-	return $salt_result[0];
-}
-
-function save_salt($user_id, $passwd)
-{
-	$dbh = db_connect();
-	$salt = generate_salt();
-	$hash = salted_hash($passwd, $salt);
-	$salting_q = "UPDATE Users SET Salt = '$salt'" .
-		", Passwd = '$hash' WHERE ID = '$user_id'";
-	return db_query($salting_q, $dbh);
-}
-
 function generate_salt()
 {
-	return md5(uniqid(rand(), true));
+	return md5(uniqid(mt_rand(), true));
 }
 
 function salted_hash($passwd, $salt)
 {
-	if (strlen($salt) != 32) {
-		trigger_error('Salt does not look like an md5 hash', E_USER_WARNING);
-	}
-	return md5($salt . $passwd);
+	if (!isset($salt))
+		return md5($passwd); /* Legacy */
+		
+	return hash('sha512', pack("H*" , $salt) . "##" . pack("H*" , md5($passwd)));
 }

