哪种哈希算法用于密码PHP

时间:2012-09-06 08:39:50

标签: php encryption passwords

  

可能重复:
  Secure hash and salt for PHP passwords

对于加密php文件中的密码,我想更改为 sha256 md5 而不是使用 sha1 作为 iIwent 进行在线研究,他们说 sha1 不是太安全了

如何更改 php 文件?

<?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;
}

}

?> 

5 个答案:

答案 0 :(得分:6)

最安全的散列密码方式是使用BCrpyt
MD5,SHA1,SHA256被认为不安全。

有关此问题的更多信息,请参阅此有关安全性的帖子: https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords

要实现BCrpyt密码哈希,请参阅:How do you use bcrypt for hashing passwords in PHP?

答案 1 :(得分:3)

BCrypt是在PHP中加密密码的方法。以下是一些可以帮助您的代码:

<?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$'; }

答案 2 :(得分:1)

花费大量时间玩不同的哈希算法和您自己的完美存储方式。有可能在这里犯了一些错误,最好的哈希算法无法拯救你。

我强烈建议人们坚持使用标准库。它们具有相当好的功能,主机系统无论如何。这尤其意味着crypt功能,可能会被操作系统的各个部分大量使用。

现在,当我提到crypt时,有些人会心脏病发作。这很好,因为这意味着他们只是重复原始UNIX时代的信息,并且不太了解。 现代 crypt可以做的远不止DES。只是不要与DES一起使用。

以下是我的Linux系统上crypt手册页的一部分(但BSD也支持此功能)。所有这些都应该直接在PHP中提供:

          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

使用此方案可以获得的巨大好处,实际上您可以在系统中实现不同的方案。

假设您有一些用户在您仍在使用MD5的时间设置了密码。但是,任何密码都应使用SHA-256加密。也许在几年内,您希望慢慢迁移到另一个标准,也许Bcrypt。没问题。它只需要一个新的ID。这些哈希值可能由所有标准软件支持。需要它们作为unix登录?没问题。 Apache HTTP身份验证?没问题。因为它使用的是操作系统标准。

在验证时,将根据上次设置密码时使用的方案对其进行测试。所以向后兼容转发兼容

如果您要迁移到新方案,请说出SHA-3,只需将默认哈希值更改为最新,然后要求用户设置新密码,并在某些时候禁用所有具有旧哈希ID的密码。它使有意义地存储ID和散列。

使用SHA-256方案所需要做的就是生成一个具有方案$5$<16-chars-of-salt>$的哈希。如果您想要SHA-512,请使用$6$<16-chars-of-salt>$

这是非常简单的代码:

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

将产生

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

正确加盐的SHA-512密码哈希。 不要重新发明轮子。

答案 3 :(得分:0)

你可以使用

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

而不是

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

在功能

hashSSHA   

答案 4 :(得分:0)

您可以将哈希函数更改为sha256,md5或其他任何内容,但如果您的数据库已经填充了sha1-hashed密码,它将无法正常工作。在这种情况下,没有办法在不丢弃遗留数据的情况下更改散列函数。