LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   PHP: how to validate a password from htpasswd (https://www.linuxquestions.org/questions/programming-9/php-how-to-validate-a-password-from-htpasswd-4175589072/)

robertjinx 09-09-2016 05:12 AM

PHP: how to validate a password from htpasswd
 
Hello, I'm creating a script/page using PHP which will give the possibility to a user to change his password from htpasswd file, but I'm not sure how to ensure that the current password matches the password from htpasswd.

Does anybody know how to validate 'current password' against the password saved in htpasswd?

keefaz 09-09-2016 05:21 AM

It depends on http password format

See code example in
http://httpd.apache.org/docs/2.2/mis...cryptions.html

robertjinx 09-09-2016 07:28 AM

Quote:

Originally Posted by keefaz (Post 5602841)
It depends on http password format

See code example in
http://httpd.apache.org/docs/2.2/mis...cryptions.html

I use 'MD5' for passwords.

keefaz 09-09-2016 08:28 AM

To verify password, php should be able to open and read the file where http passwords are stored

Then you get the line that starts with "Username:<crypted password>" and compare the crypted password with the password you want to check crypted with same algorythm

Function to crypt password:
https://www.virendrachandak.com/tech...htpasswd-file/

sundialsvcs 09-09-2016 10:06 AM

Passwords are ordinarily stored in databases, not in files.

The most common strategy is to store a "salted hash." The password, plus a random number (the "salt"), is hashed using SHA1 (not MD5 ...), and both the resulting hash and the random number are stored. (The random number is not concealed.)

robertjinx 09-10-2016 04:24 AM

Quote:

Originally Posted by sundialsvcs (Post 5602953)
Passwords are ordinarily stored in databases, not in files.

The most common strategy is to store a "salted hash." The password, plus a random number (the "salt"), is hashed using SHA1 (not MD5 ...), and both the resulting hash and the random number are stored. (The random number is not concealed.)

Yes, the idea is good for new passwords, but what about old passwords which used a 'salt' which hasn't been saved? How do I ensure that the current password is correct or how do I validate a old password to ensure is the right user?

ntubski 09-10-2016 06:42 AM

Quote:

Originally Posted by robertjinx (Post 5603287)
Yes, the idea is good for new passwords, but what about old passwords which used a 'salt' which hasn't been saved?

If you don't have the salt then you might as well throw the hash away. However you talked about htpasswd in the first post, according to Apache's htpasswd format documentation, the salt should be in that file.

Quote:

Originally Posted by sundialsvcs (Post 5602953)
Passwords are ordinarily stored in databases, not in files.

The most common strategy is to store a "salted hash." The password, plus a random number (the "salt"), is hashed using SHA1 (not MD5 ...), and both the resulting hash and the random number are stored. (The random number is not concealed.)

SHA1 is not sufficient for password storing. Something like https://en.wikipedia.org/wiki/Scrypt should be used, see also Cryptographic Hash Functions Are Not Password Hash Functions, and the htpasswd documentation linked above:
Quote:

SHA1
"{SHA}" + Base64-encoded SHA-1 digest of the password. Insecure.


ccj4467 09-12-2016 12:30 PM

Here is quick little PHP program that reads an APACHE htpasswd file and checks if the input password is valid

Code:

<?php
// APR1-MD5 encryption method (windows compatible)
function crypt_apr1_md5($plainpasswd, $salt)
{
    $tmp = "";
    $len = strlen($plainpasswd);
    $text = $plainpasswd.'$apr1$'.$salt;
    $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
    for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
    for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; }
    $bin = pack("H32", md5($text));
    for($i = 0; $i < 1000; $i++)
    {
        $new = ($i & 1) ? $plainpasswd : $bin;
        if ($i % 3) $new .= $salt;
        if ($i % 7) $new .= $plainpasswd;
        $new .= ($i & 1) ? $bin : $plainpasswd;
        $bin = pack("H32", md5($new));
    }
    for ($i = 0; $i < 5; $i++)
    {
        $k = $i + 6;
        $j = $i + 12;
        if ($j == 16) $j = 5;
        $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
    }
    $tmp = chr(0).chr(0).$bin[11].$tmp;
    $tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
 
    return "$"."apr1"."$".$salt."$".$tmp;
}

function get_htpasswd ( $passwdFile, $username )
{
    $lines = file($passwdFile);
    foreach ($lines as $line)
    {
        $arr = explode(":", $line);
        $fileUsername = $arr[0];
        if ($fileUsername == $username)
        {
            $filePasswd = trim($arr[1]);
            return $filePasswd;
        }
    }
    return false;
}

function matches($password, $filePasswd)
{
    if (strpos($filePasswd, '$apr1') === 0)
    {
        // MD5
        $passParts = explode('$', $filePasswd);
        $salt = $passParts[2];
        $hashed = crypt_apr1_md5($password, $salt);
        return $hashed == $filePasswd;
    }
    elseif (strpos($filePasswd, '{SHA}') === 0)
    {
        // SHA1
        $hashed = "{SHA}" . base64_encode(sha1($password, TRUE));
        return $hashed == $filePasswd;
    }
    elseif (strpos($filePasswd, '$2y$') === 0)
    {
      // Bcrypt
      return password_verify ($password, $filePasswd);
    }
    else
    {
        // Crypt
        $salt = substr($filePasswd, 0, 2);
        $hashed = crypt($password, $salt);
        return $hashed == $filePasswd;
    }
    return false;
}

$username = $argv[1];
$password = $argv[2];

$filePasswd = get_htpasswd( 'passwordfile', $username );

if ( matches($password, $filePasswd) )
{
    echo "Correct password\n";
}
else
{
    echo "Incorrect username or password\n";
}
?>

It reads the username and password from the command line and looks in passwordfile for the user. Change the first arg in the call to get_htpasswd to your actual password file. This supports all of htpasswd's hash methods.


All times are GMT -5. The time now is 01:43 AM.