0

可能重复:
PHP 密码的安全哈希和盐

对于php文件中密码的加密,我想改成sha256或者md5,而不是使用sha1,因为去网上研究,他们说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;
}

}

?> 
4

5 回答 5

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?

于 2012-09-06T08:55:38.110 回答
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$'; }
于 2012-09-06T09:29:21.077 回答
1

不要花太多时间玩弄不同的哈希算法和您自己的完美存储方式。很可能在这里犯了一些错误,最好的散列算法也救不了你。

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

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

这是crypt我的 Linux 系统上手册页的一部分(但 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 方案所需要做的就是生成一个具有该方案的 Hash $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 密码哈希。不要重新发明轮子。

于 2012-09-07T14:44:53.000 回答
0

您可以使用

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

代替

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

在功能上

hashSSHA   
于 2012-09-06T08:46:32.843 回答
0

您可以将散列函数更改为 sha256、md5 或其他任何值,但如果您的数据库已经填充了 sha1 散列密码,则它不会很好地工作。在这种情况下,如果不丢弃遗留数据,就无法更改哈希函数。

于 2012-09-06T08:47:55.780 回答