Which hashing algorithm to use for Password PHP [d

2019-09-09 14:19发布

问题:

Possible Duplicate:
Secure hash and salt for PHP passwords

For the encrypting of the password in the php file, I want to change to sha256 or md5 instead of using sha1 as iIwent to research online and they say sha1 is not so secure.

How do I change in the php file?

<?php

class DB_Functions {

private $db;

//put your code here
// constructor
function __construct() {
    require_once 'DB_Connect.php';
    // connecting to database
    $this->db = new DB_Connect();
    $this->db->connect();
}

// destructor
function __destruct() {

}

/**
 * Storing new user
 * returns user details
 */
public function storeUser($name, $nric, $email, $license, $address, $postal_code, $password) {
    $hash = $this->hashSSHA($password);
    $encrypted_password = $hash["encrypted"]; // encrypted password
    $salt = $hash["salt"]; // salt
    $result = mysql_query("INSERT INTO users(name, nric, email, license, address, postal_code, encrypted_password, salt, created_at) VALUES('$name', '$nric', '$email', '$license', '$address', '$postal_code', '$encrypted_password', '$salt', NOW())");
    // check for successful store
    if ($result) {
        // get user details 
        $uid = mysql_insert_id(); // last inserted id
        $result = mysql_query("SELECT * FROM users WHERE uid = $uid");
        // return user details
        return mysql_fetch_array($result);
    } else {
        return false;
    }
}

/**
 * Get user by nric and password
 */
public function getUserByNricAndPassword($nric, $password) {
    $result = mysql_query("SELECT * FROM users WHERE nric = '$nric'") or die(mysql_error());
    // check for result 
    $no_of_rows = mysql_num_rows($result);
    if ($no_of_rows > 0) {
        $result = mysql_fetch_array($result);
        $salt = $result['salt'];
        $encrypted_password = $result['encrypted_password'];
        $hash = $this->checkhashSSHA($salt, $password);
        // check for password equality
        if ($encrypted_password == $hash) {
            // user authentication details are correct
            return $result;
        }
    } else {
        // user not found
        return false;
    }
}

/**
 * Check user is existed or not
 */
public function isUserExisted($nric) {
    $result = mysql_query("SELECT nric from users WHERE nric = '$nric'");
    $no_of_rows = mysql_num_rows($result);
    if ($no_of_rows > 0) {
        // user existed 
        return true;
    } else {
        // user not existed
        return false;
    }
}

/**
 * Encrypting password
 * @param password
 * returns salt and encrypted password
 */
public function hashSSHA($password) {

    $salt = sha1(rand()); //algorithm hash
    $salt = substr($salt, 0, 10);
    $encrypted = base64_encode(sha1($password . $salt, true) . $salt);
    $hash = array("salt" => $salt, "encrypted" => $encrypted);
    return $hash;
}

/**
 * Decrypting password
 * @param salt, password
 * returns hash string
 */
public function checkhashSSHA($salt, $password) {

    $hash = base64_encode(sha1($password . $salt, true) . $salt);

    return $hash;
}

}

?> 

回答1:

The most secure way of hashing passwords, would be to use BCrpyt
MD5, SHA1, SHA256 is considered not secure.

For more information on this matter, see this post on security: https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords

For implementing BCrpyt password hashing see: How do you use bcrypt for hashing passwords in PHP?



回答2:

BCrypt is the way to go when it comes to encrypting your passwords in PHP. Here is some code that should help you along the way:

<?php
/*
By Marco Arment <me@marco.org>.
This code is released in the public domain.

THERE IS ABSOLUTELY NO WARRANTY.

Usage example:

// In a registration or password-change form:
$hash_for_user = Bcrypt::hash($_POST['password']);

// In a login form:
$is_correct = Bcrypt::check($_POST['password'], $stored_hash_for_user);

// In a login form when migrating entries gradually from a legacy SHA-1 hash:
$is_correct = Bcrypt::check(
$_POST['password'],
$stored_hash_for_user,
function($password, $hash) { return $hash == sha1($password); }
);
if ($is_correct && Bcrypt::is_legacy_hash($stored_hash_for_user)) {
$user->store_new_hash(Bcrypt::hash($_POST['password']));
}

*/

class Bcrypt
{
    const DEFAULT_WORK_FACTOR = 8;

    public static function hash($password, $work_factor = 0)
    {
        if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');

        if (! function_exists('openssl_random_pseudo_bytes')) {
            throw new Exception('Bcrypt requires openssl PHP extension');
        }

        if ($work_factor < 4 || $work_factor > 31) $work_factor = self::DEFAULT_WORK_FACTOR;
        $salt =
            '$2a$' . str_pad($work_factor, 2, '0', STR_PAD_LEFT) . '$' .
            substr(
                strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'),
                0, 22
            )
        ;
        return crypt($password, $salt);
    }

    public static function check($password, $stored_hash, $legacy_handler = NULL)
    {
        if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');

        if (self::is_legacy_hash($stored_hash)) {
            if ($legacy_handler) return call_user_func($legacy_handler, $password, $stored_hash);
            else throw new Exception('Unsupported hash format');
        }

        return crypt($password, $stored_hash) == $stored_hash;
    }

    public static function is_legacy_hash($hash) { return substr($hash, 0, 4) != '$2a$'; }
}


// =============================================================================
// Or, if you don't want the class structure and just want standalone functions:
// =============================================================================

function bcrypt_hash($password, $work_factor = 8)
{
    if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');

    if (! function_exists('openssl_random_pseudo_bytes')) {
        throw new Exception('Bcrypt requires openssl PHP extension');
    }

    if ($work_factor < 4 || $work_factor > 31) $work_factor = 8;
    $salt =
        '$2a$' . str_pad($work_factor, 2, '0', STR_PAD_LEFT) . '$' .
        substr(
            strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'),
            0, 22
        )
    ;
    return crypt($password, $salt);
}

function bcrypt_check($password, $stored_hash, $legacy_handler = NULL)
{
    if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');

    if (bcrypt_is_legacy_hash($stored_hash)) {
        if ($legacy_handler) return call_user_func($legacy_handler, $password, $stored_hash);
        else throw new Exception('Unsupported hash format');
    }

    return crypt($password, $stored_hash) == $stored_hash;
}

function bcrypt_is_legacy_hash($hash) { return substr($hash, 0, 4) != '$2a$'; }


回答3:

Do not spend to much time playing around with different hash algorithms and your own perfect way of storing them. Chances are that you make some mistake here, and the best hashing algorithm cannot save you.

I strongly advise people to stick to the standard libraries. They have pretty good functionality that is used by the host system anyway. This means in particular the crypt function, which is likely used heavily by various parts of your operating system.

Now some people will get a heart attack when I mention crypt. And this is good, because it means they are just repeating information from the original UNIX days again, and have not understood much. Modern crypt can do much more than DES. Just don't use it with DES.

Here is part of the crypt man page on my Linux system (but this is also supported by BSD). All of this should be directly available in PHP, too:

          ID  | Method
          ---------------------------------------------------------
          1   | MD5
          2a  | Blowfish (not in mainline glibc; added in some
              | Linux distributions)
          5   | SHA-256 (since glibc 2.7)
          6   | SHA-512 (since glibc 2.7)

   So   $5$salt$encrypted   is   an   SHA-256   encoded    password    and
   $6$salt$encrypted is an SHA-512 encoded one.

   "salt" stands for the up to 16 characters following "$id$" in the salt.
   The encrypted part of the password string is the actual computed  pass-
   word.  The size of this string is fixed:

   MD5     | 22 characters
   SHA-256 | 43 characters
   SHA-512 | 86 characters

The massive benefit you get from using this scheme is that you can in fact have different schemes in effect in your system.

Say you have some users who set their password in a time where you were still using MD5. However, any new password should be encrypted using SHA-256. And maybe in a few years, you want to slowly migrate to yet another standard, maybe Bcrypt. No problem. It just needs a new ID. And these hashes are probably supported by all the standard software you have. Need them as unix logins? No problem. Apache HTTP authentication? no problem. Because it's using the operating system standard.

And on verification, it will be tested against the scheme that was in use when the password was last set. So it is backwards compatible, and forwards compatible.

If you want to migrate to a new scheme, say SHA-3 when it is out, you can just change the default hash to the latest, then ask the users to set a new password, and at some point disable all passwords that have the old hash ID. It makes tons of sense to store an ID along with the hash.

All you need to do to use SHA-256 scheme, is to generate a Hash that has the scheme $5$<16-chars-of-salt>$. If you want SHA-512, use $6$<16-chars-of-salt>$.

It's very simple code:

crypt("Hello",'$6$CygnieHyitJoconf$')

will produce

$6$CygnieHyitJoconf$vkGJm.nLrFhyWHhNTvOh9fH/k7y6k.8ed.N7TqwT93hPMPfAOUsrRiO3MmQB5xTm1XDCVlW2zwyzU48epp8pY/

A properly salted SHA-512 password hash. Don't reinvent the wheel.



回答4:

you can use

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

instead of

$encrypted = base64_encode(sha1($password . $salt, true));

in function

hashSSHA   


回答5:

You can change hash function to sha256, md5, or anything, but it will not work well if your DB is already filled with sha1-hashed passwords. In this case there's no way to change hash function without discarding legacy datas.