简单但安全的密码哈希

时间:2014-06-25 22:24:45

标签: php passwords password-storage

我正在寻找一种简单(或尽可能简单)但安全的方法,用于在将用户密码提交到数据库然后从数据库中检索时对用户密码进行散列和腌制。在过去3个小时的研究中,每个人都会说数百种不同的方法是最好的方法。

我正在寻找一种相对简单的方法,它也可以保证用户帐户安全。显然,安全这个术语可以用不同的方式解释,但我只想要它,至少对于一个潜在的黑客(或任何你称之为“悲伤”的人)来说,要获得对用户帐户的访问权限是非常困难的。

我很欣赏我至少应该尝试过一些东西,但是对于我的目的来说,它们看起来都很复杂且过于安全。

我尝试使用password_hash(),但似乎我正在运行早于PHP的5.5版本。我知道下面的代码存在问题,但它只是我正在研究的一个人项目的起点,以便更好地学习PHP。

目前的注册表格

$username = $_POST['username'];
$password = $_POST['password'];

try {   

    $result = $db->prepare("INSERT INTO 
                            user_info 
                            SET 
                            username = :user,
                            pass = :pass
                            ");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
}

catch (Exception $e) {
    echo "Could not create username";
}

if (isset($_POST['submit'])) { 
    foreach ($_POST as $field) {
        if (empty($field)) {
            $fail = true;
        }
        else {
            $continue = false;
        }
    }
    if ($field == $fail) {
        echo "You must enter a username and/or password";
    }
    else {
        echo "Your account has been successfully created.";
    }
     }

登录逻辑

$username = $_POST['username'];          
$password = $_POST['password'];

try {   

    $result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
    $rows = $result->fetch(PDO::FETCH_NUM);
}

catch (Exception $e) {
    echo "Could not retrieve data from database";
    exit();
}

if ($password = $rows) {
    session_start();
    $_SESSION['username'] = $_POST['username'];
    $_SESSION['loggedin'] = true;
    include("inc/redirect.php");

} else {
    if (isset($_POST['login'])) {
        echo "Username or password incorrect (passwords are case sensitive)";
    }
}

4 个答案:

答案 0 :(得分:1)

使用sha1函数http://www.php.net/manual/en/function.sha1.php

这很简单。在输入参数中传递密码,然后将其保存在数据库中。

如果要检查密码是否正确,只需将sha1(密码)与存储值进行比较即可。

示例:

$ passwordEncrypted = sha1($ password)

  
    
      

在数据库中保存$ passwordEncrypted

    
  

当用户想要登录时:

检查这个条件:

if(sha1($ password)== $ passwordEncrypted)

以下是完整的代码:

$username = $_POST['username'];

$password = $_POST['password'];
$passwordEncrypted = sha1($password) 

    try {   

        $result = $db->prepare("INSERT INTO 
                                user_info 
                                SET 
                                username = :user,
                                pass = :pass
                                ");
        $result->bindParam(':user', $username);
        $result->bindParam(':pass', $passwordEncrypted);
        $result->execute();
    }

    catch (Exception $e) {
        echo "Could not create username";
    }

    if (isset($_POST['submit'])) { 
        foreach ($_POST as $field) {
            if (empty($field)) {
                $fail = true;
            }
            else {
                $continue = false;
            }
        }
        if ($field == $fail) {
            echo "You must enter a username and/or password";
        }
        else {
            echo "Your account has been successfully created.";
        }
         }

答案 1 :(得分:0)

答案 2 :(得分:0)

使用salt和sha256加密算法

<?php
// create user
$password = $_POST['password'];
$salt = mcrypt_create_iv(22, MCRYPT_DEV_URANDOM);
$pass = hash("sha256", $salt.$password.$salt);
// save salt and password hash into database

// to validate user
// 1 - get salt and password hash from database
// 2 - prepend and append salt to the posted password
// 3 - encrypt with the same algorithm
// 4 - compare with stored password hash. 

答案 3 :(得分:0)

使用password_hash(),您走在正确的轨道上。对于PHP版本5.3.7 - 5.5,您可以使用compatibility pack,稍后当您切换到较新的PHP版本时,您只需从项目中删除此php文件,代码仍将运行。

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

即使对于低于5.3.7的PHP版本,您也可以使用兼容包。您只需编辑第55行并将算法从sprintf("$2y$%02d$", $cost);更改为sprintf("$2a$%02d$", $cost);。这当然不是最佳选择,但对于5.3和5.3.7之间的PHP,它是最好的。

其他算法(如SHA *或MD5)的问题在于它们的速度太快了。可以使用通用硬件计算大约3 Giga SHA-1 per second,这使得暴力破解变得太容易了。要测试整个英语词典,您只需要几分之一毫秒。这就是为什么人们应该使用像BCrypt或PBKDF2这样的成本因子的哈希算法,它们允许控制计算单个哈希的必要时间。