1

由于 PHP sha1() 可以通过与一长串哈希值进行比较很容易地被破坏 - 这会更好吗(基本上 - 一遍又一遍地应用 sha1() 来尝试通过减慢哈希过程来使暴力破解变得不切实际) :

<?php
    $iterations = 100000;
    $pass       = 'hyugf67rf76dt564d5r76';
    $salt       = '6t6755636459679guytfugiuhbguiygfytcdtresr5tdt5yfuybiugbuyfr56d45esertdcftyuuguy';
    $hash       = '';

    for ($i=0; $i<$iterations;$i++) {
        $hash = sha1($hash . $pass . $salt);
    }

    echo $salt . $hash;
?>
4

2 回答 2

2

与其sha1一遍又一遍地应用,为什么不crypt()使用更强的盐执行一次呢?

如果你有 PHP 5.5 +,你可以简单地去password_hash()

此处还提供了 password_hash() 的用户态实现

提示:您可以结合password_hash()上面文档链接的示例 #4 和 #3 来创建更强的散列。


或使用phpass

phpass 支持的首选(最安全)散列方法是 OpenBSD 风格的基于 Blowfish 的 bcrypt,也支持我们的公共域 crypt_blowfish 包(用于 C 应用程序),在 PHP 中称为 CRYPT_BLOWFISH,回退到 BSDI 风格的扩展基于 DES 的散列,在 PHP 中称为 CRYPT_EXT_DES,最后的手段是回退到在 phpass 本身中实现的基于 MD5 的加盐和可变迭代计数密码散列(也称为可移植散列)。

于 2014-04-19T13:15:28.013 回答
1

A better way to approach the problem, is by using a hashing algorithm that has this cost-intensity built-in, instead of using a custom function. If the resulting hash is not truly random, this could be a security problem.

That doesn't answer your question though, so I'll try to do that now.

Cost-intensity

If applied correctly, algorithms that are more cost-intensive make it more cost-intensive for an attacker to crack all passwords from a database. If applied incorrectly though, most of this cost-intensity can be bypassed. This is why I recommend using an algorithm that is designed to be cost-intensive, rather than trying to create something yourself.

Salts

A database-wide salt only protects you from rainbow tables without a salt. When an attacker obtains your database with passwords, and knows the salt, they can make their own rainbow table with your salt, and crack every password in the database with this rainbow table. Users with the same password have the same hash in the database.

A per-account salt (a salt that is different for each account), an attacker has to crack each password individually. Users with the same password have a different hash in the database. Cracking passwords is much more costly now.

Iteration

What you should be wary of when reapplying, is that the attacker should not be able to create a lookup table for part of this iteration. In other words: The iteration should contain something that is different for every user, and even better, different for every password tried for an user. Since you re-use the password in the algorithm, this should be no problem.*

A little change to the algorithm could however allow an attacker to bypass most of the iteration. In the following code, the attacker could create a lookup table that translates a hash to a hash with sha1 applied 99.999. In fact, such a table can be created by applying it just once on every hash, then using that lookup table multiple times. Instead of needing to apply sha1 100.000 times for every password, this now has been reduced to creating a lookup table, applying sha1 exactly once for every password, and looking up a hash in a lookup table once for every password. Even with a per-user salt, this would make no difference to the lookup table.

If you would use a per-user salt and change the line with //here to sha1($hash . $salt), the attacker has to create such a table for every unique salt in the database. This is slightly more work, but still much less than the work an attacker has to do when he has to calculate every hash for every password they try out.

<?php
    #Bad code below
    $iterations = 100000;
    $pass       = 'hyugf67rf76dt564d5r76';
    $salt       = '6t6755636459679guytfugiuhbguiygfytcdtresr5tdt5yfuybiugbuyfr56d45esertdcftyuuguy';
    $hash       = sha1($hash . $pass . $salt);

    for ($i=0; $i<$iterations;$i++) {
        $hash = sha1($hash); //Here
    }

    echo $salt . $hash;
?>

* I am by no means a security expert. I am a student with some knowledge about algorithms, and some knowledge about security, but the fact I don't see a problem doesn't mean there isn't a problem.

于 2014-04-19T14:21:04.047 回答