使用Hash和Salt与MYSQL表

时间:2013-06-09 20:23:52

标签: php mysql

我有一个MySQL'用户'表,其中包含以下列:uname,hash,salt和pwd。我正在测试使用此表获取用户访问权限的PHP登录页面。我目前还没有系统设置来注册用户,所以通过手动将数据添加到表中进行测试......

uname: 'testuser',
pwd: 'password'

处理检查密码的php函数如下:

function checkPwd($uname, $pwd){
    // Get the hash and salt for this user:
    $q = "SELECT hash, salt FROM users WHERE uname = '".mysql_real_escape_string($uname)."';";
    $res = mysql_query($q) or die("Could not retrieve user login data " . mysql_error());
    $tmp = mysql_fetch_assoc($res);
    $hash = $tmp['hash'];
    $salt = $tmp['salt'];
    // Hash and salt $pwd so we can make a comparison:
    $hashedInput = sha1($salt . $pwd);
    if($hash == $hashedInput) return true; // Return true if the hashed and salted $pwd matches DB entry
    return false;
}

它显然不起作用,事情是我不是真正理解做事的哈希和盐的方式。如何使用上述功能测试我的登录页面以确保安全。我是否必须在盐和哈希字段中输入任何内容?

4 个答案:

答案 0 :(得分:2)

使用加密哈希函数的目的是values created by those functions are not reversible。因此,如果有人拥有密码的哈希值,那么确定密码除了暴力破解之外没有可行的方法。

但是,有些技术可以通过使用预先计算的查找表进行时间/空间权衡来破坏暴力破解。这些可以是已知 hash 密码对的简单查找表。或者是这种查找表的扩展类型,即所谓的Rainbow table

这是salt的用武之地。它用于add additionally entropy用户的密码,因此散列函数的每个输入都是唯一的,因此也创建了一个唯一的哈希:password将是最多的肯定已经在查找表中,xi2B9LMweH/jM8Khxedls+password当然不会。由于彩虹表的构建方式,攻击者需要为每个独特的盐构建一个Rainbow表。

请注意,salt的目的只是为了打败这种查找表攻击。如果已知盐,或者无论如何都是蛮力攻击,人们仍然可以进行字典攻击。如果密码不好,仍然可以猜测或强制使用。

现在至于实施部分,最好不要重新发明轮子。请查看Secure hash and salt for PHP passwordsHow do you use bcrypt for hashing passwords in PHP?

答案 1 :(得分:0)

  

我目前还没有系统设置来注册用户,因此通过以下方式手动向表中添加数据进行测试......显然不能正常工作,

它不起作用?要使您的函数正常工作,您需要在hash中插入一个与您的salting方法(sha1行)匹配的值。

  事情是我不是真正理解哈希和盐的方式   做事。

salt的目的是使得到的哈希值“不可预测”。哈希是一种方式,但是黑客使用哈希字典来用蛮力来识别密码(Rainbow table)。

salt可以与哈希一起存储在数据库中 - 它不需要保密。然而,攻击者在知道盐的情况下重新生成他们的词典会相当微不足道。这就是使用像Scrypt这样的方法更好的原因。 Scrypt需要大量的CPU时间和内存来计算单个哈希值。

Scrypt哈希可以配置为每个哈希需要100毫秒。这意味着您每秒可以生成10个哈希值。常规的散列方法,如SHA1,是为了提高速度而构建的。例如:使用比特币挖掘(使用散列),您可以使用hardware生成5,000 Mega-Has-Second,只需300美元。 GPU也擅长计算哈希值。像Scrypt这样的方法非常适合保护密码,因为它们难以暴力破解。

  

如何使用该功能测试我的登录页面以确保安全   以上。我是否必须在盐和哈希字段中输入任何内容?

是的,您需要在哈希列中输入一个值。在测试任何登录之前,您似乎需要做更多的工作。

由于您不熟悉这些主题,我强烈建议使用一个可以为您处理这些事情的通用PHP框架。至少检查这些框架如何实现身份验证。 Security stack exchange也是一个很好的资源。

答案 2 :(得分:-1)

您只需要“salt”和“password”,Salt的作用是创建一个随机字符串值,以便像使用公钥一样使用它来加密密码。

例如:$ salt = base_convert(sha1(uniqid(mt_rand(),true)),16,36);

现在你可以使用这个Salt加密你的密码:$ pwd = sha1($ salt。$ POST ['pwd']); 然后你在数据库中保存$ pwd和$ salt。

现在,如果您要检查登录名:您从数据库中对唯一值(电子邮件,用户名)执行SELECT查询,然后通过solt和test来加密输入的密码。

编辑:

对于Salt系列:我们为你选择16和36之间的任意数字之间的uniqid(php.net/manual/fr/function.uniqid.php)创建一个随机值,然后sha1使其更强最后我们用php.net/manual/fr/function.base-convert.php

清理我们的Salt

希望有所帮助。

答案 3 :(得分:-1)

标准密码安全方法是这样的:

您的服务器端数据库应为每个用户存储两列:username和hash。如果您想为每个用户使用单独的盐,那么它也可以存储。为站点提供单一盐并在哈希中包含用户名更简单。如果您不想在哈希中包含用户名,那么建议为每个用户添加一个单独的盐(可以根据用户名和特定于站点的内容计算,如果需要,或者只是随机的)。

最重要的一点是:密码永远不应存储在数据库中。

当用户注册并选择密码时,请使用密码+ salt +用户名(或密码+唯一盐,如果您要使用该路由)构建字符串,然后通过加密安全散列函数运行此字符串。 MD5已过时且不太安全。 SHA1可能很好。 SHA256会更好。不要使用分组密码AES - 这些密码不是设计为抗冲突的。将此哈希的结果存储在表中。

当用户下次登录时,请使用他的用户名和密码,添加盐,并计算相同的哈希函数。将其与存储在数据库中的数据进行比较。如果匹配,请让她进来。如果你这样做,即使您的数据库已发布,也没有人能够使用它找到任何人的密码。

为了额外的安全性(如果你做了其余的事情,但现在可能有些过分,但是对于未来验证有好处),请使用故意缓慢且复杂的哈希函数进行计算。一种方法是简单地迭代你的哈希函数几百次。另一个是使用像scrypt这样的记忆难题。

腌制的目的是防止“彩虹桌”攻击,潜在的攻击者可以预先计算数十亿个潜在密码的哈希值,而不必通过暴力破解它们。