Question

Since the PHP sha1() can be broken quite easily by comparing against a long list of hashes - would this be any better (basically - applying sha1() over and over again to try and make brute forcing impractical by slowing the hashing process down):

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

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

    echo $salt . $hash;
?>
Was it helpful?

Solution

Instead of applying the sha1 over again and again , why not implement crypt() once with a stronger - salt ?

If you have PHP 5.5 +, you could simply go for password_hash()

A userland implementation of password_hash() is also available here

HINT : You could combine the examples #4 and #3 of the password_hash()documentation link above to creater a stronger hash.


or use phpass

The preferred (most secure) hashing method supported by phpass is the OpenBSD-style Blowfish-based bcrypt, also supported with our public domain crypt_blowfish package (for C applications), and known in PHP as CRYPT_BLOWFISH, with a fallback to BSDI-style extended DES-based hashes, known in PHP as CRYPT_EXT_DES, and a last resort fallback to MD5-based salted and variable iteration count password hashes implemented in phpass itself (also referred to as portable hashes).

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top