MySQL - 如何加密密码

时间:2013-04-22 18:23:29

标签: mysql sql authentication encryption

我想了解如何编辑代码以加密用户密码。用户填写提交customerRegister.php的HTML表单,然后在提交查询之前进行一系列验证。

customerRegister.php

registerUser($_POST['firstName'], $_POST['lastName'], $_POST['username'], $_POST['houseNo'], $_POST['StreetName'], $_POST['town'], $_POST['postCode'], $_POST['emailAddress'], $_POST['phoneNumber'], $_POST['password'], $_POST['conPassword'],$_POST['carRegistration'],$_POST['carMake'],$_POST['carModel'],$_POST['carYear'],$_POST['carEngineSize'],$_POST['carFuel']);

 function registerUser($firstName, $lastName, $username, $houseNo, $streetName, $town, $postCode, $emailAddress, $phoneNumber, $password, $conPassword, $registration, $carMake, $carModel, $carYear, $carEngineSize, $carFuel) {

      $registerQuery = new UserLoginQueries();

/********************************
SERIES OF VALIDATIONS
********************************/

$registerQuery->insertUser($firstName, $lastName, $username, $houseNo, $streetName, $town, $postCode, $emailAddress, $phoneNumber, $password);

然后将这些详细信息传递给执行查询的userLoginQueries.php。

userLoginQueries.php

  public function insertUser($custFirstName, $custLastName, $username, $houseNo, $streetName, $town, $postCode, $email, $number, $pass) {
    $sth = $this->conn->prepare("INSERT INTO `customer`(`CustFirstName`, `CustLastName`, `HouseNo`, `StreetName`, `Town`, `PostCode`, `EmailAddress`, `PhoneNumber`, `Username`, `Password`) VALUES (?,?,?,?,?,?,?,?,?,?)");
    $sth->bindValue (1, $custFirstName);
    $sth->bindValue (2, $custLastName);
    $sth->bindValue (3, $houseNo);
    $sth->bindValue (4, $streetName);
    $sth->bindValue (5, $town);
    $sth->bindValue (6, $postCode);
    $sth->bindValue (7, $email);
    $sth->bindValue (8, $number);
    $sth->bindValue (9, $username);
    $sth->bindValue (10, $pass);
    $sth->execute(); 
  }

当用户输入登录信息时,将运行以下查询:

  public function queryLogin($username, $password) {
    $sth = $this->conn->prepare("SELECT * FROM customer WHERE Username = ? AND Password = ? AND UserType = 'Customer'");
    $sth->bindValue (1, $username);
    $sth->bindValue (2, $password);
    $sth->execute();
    $count = $sth->rowCount();
    return $count;
    }

如何修改我的代码以便加密用户密码?

3 个答案:

答案 0 :(得分:2)

您应该使用散列算法http://en.wikipedia.org/wiki/Hash_function(单向算法)使用salt存储您的密码,请参阅http://en.wikipedia.org/wiki/Salt_(cryptography)

其中一个根本原因是,如果您的数据库遭到入侵,攻击者就不会知道实际的密码是什么。

一个简单的哈希算法,是sha-1。您可以在http://php.net/manual/en/function.sha1.php

查看如何使用它

使用哈希哈希

以下内容可能有所帮助: -

$sth->bindValue (2, sha1($password . "random private stuff here as salt"));

下次要验证密码时,只需将输入的密码和盐与实际值和盐进行比较即可。这将告诉您密码是否正确,而无需以明文保存用户密码。

为什么要用盐?

嗯,虽然通常一种方式的功能无法逆转,但它们可能是强制性的。这可能意味着即使您使用的是散列算法,某些密码也可能容易受到攻击。

答案 1 :(得分:2)

请看一下这个答案:How do you use bcrypt for hashing passwords in PHP?,您只需在注册用户时调用$hash = $bcrypt->hash('password'); ,然后将密码的哈希版本保存到数据库中。然后,您可以使用$isGood = $bcrypt->verify('password', $hash);

验证用户

答案 2 :(得分:2)

这里要记住的一件重要事情是“加密”是错误的单词。加密的能力意味着解密的能力,这对密码来说是一件坏事。您永远不应该永远解密密码。相反,您需要哈希密码。散列使​​用复杂的数学问题将文本输入(例如密码)提取为很长的数字。潜在数量越长,哈希可能越安全。这里重要的是哈希不能逆转。如果我的密码是“p4 $$ w0rd”,并且生成的散列是“12345”,则无法从“12345”返回“p4 $$ w0rd”。要对用户进行身份验证,当有人尝试登录时,您需要计算他们使用的密码的哈希值,然后将其与您存储的哈希值进行比较。您不能将密码存储在任何地方。永远。是的,这意味着您永远不会为用户提供恢复丢失密码的选项;你只允许他们重置它。

另外,哈希本身并不够好。事实证明,密码数据库本身一直受到危害,黑客通常已经知道你的哈希值。黑客已经投入了大量资源来创建现成的密码输入表,这些表将导致给定的哈希值。因此,对于我的示例五位“数字”哈希,它们将为从“00001”到“99999”的每个可能的哈希预先计算某事。它们对“12345”的值可能与我的“p4 $$ w0rd”不匹配,但它没关系:如果它产生相同的哈希,那就足够了。黑客可以使用它来查看受损数据库并为每个用户发现一组有效的凭据。出于这个原因,您还需要在哈希之前 salt 密码。加密密码时,在对其进行散列之前修改提交的字符串。在验证我的示例密码时,不要检查“p4 $$ w0rd”,而是首先附加我的用户帐户的salt,并对结果进行哈希处理。如果一个破解者知道我的哈希并且能够查找一个会在表中产生哈希的输入,那么对他来说就不再有用了,因为你将以一种破坏所有预先计算的哈希结果的方式修改他的输入。这让他回到蛮力猜测每一个密码。

知道并非所有哈希算法都是相同的,这一点也很重要。某些散列算法(如md5)专门创建为 fast ,因此您可以使用它们快速比较较大的文本块与已知样本。这些算法非常糟糕用于密码,因为黑客可以非常快速地猜出许多可能的密码。您需要一个非常的散列算法,因此即使使用超快速或专用硬件,黑客也需要很长时间(可能是几个世纪)来猜测真实密码。可以动态调整最佳算法,以便随着时间的推移硬件越来越快,算法变得越来越慢。这些算法的例子是“bcrypt”和“scrypt”。

最后,最重要的一课是根本不尝试构建自己的身份验证系统。身份验证的问题在于,很容易构建似乎工作的东西,但仍然存在微妙的缺陷,这样一年之后你可能会发现六个月前你被黑了。该系统甚至可以通过一些编写良好的单元测试,但仍然存在这些微妙的缺陷。您总是希望尽可能地依赖可用于您的平台的预先编写的身份验证模块。这也是允许您通过Facebook,Twitter,OpenID等登录的身份验证方案变得越来越流行的原因。