Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a way to reverse a hash without rainbow tables? [duplicate]

Possible Duplicate:
md5 decoding. How they do it?

this page suggests that a hash algorithm like md5() and sha1() can be reversed because of the huge processing power that we have nowadays. At this point i tought it was only possible with Rainbow Tables. Was i wrong?

In case Rainbow Tables is the only way to go, how someone could reverse a hash that was made with a salt?

like image 380
Hugo Mota Avatar asked Sep 23 '11 02:09

Hugo Mota


People also ask

Is it theoretically possible to reverse a hash?

Pre-Image Resistance — The idea here is that a strong hash algorithm is one that's preimage resistance, meaning that it's infeasible to reverse a hash value to recover the original input plaintext message. Hence, the concept of hashes being irreversible, one-way functions.

Can you reverse a SHA256 hash?

SHA256 is a hashing function, not an encryption function. Secondly, since SHA256 is not an encryption function, it cannot be decrypted. What you mean is probably reversing it. In that case, SHA256 cannot be reversed because it's a one-way function.

Why can't you reverse a hash function?

One big reason you can't reverse the hash function is because data is lost. Consider a simple example function: 'OR'. If you apply that to your input data of 1 and 0, it yields 1. But now, if you know the answer is '1', how do you back out the original data?

What is the best defense against rainbow table attacks?

Experts say the best defense against rainbow tables is to "salt" passwords, which is the practice of appending a random value to the password before it is encrypted.


1 Answers

Well, this question in general is a duplicate of This Question. However, to answer your exact questions:

At this point i tought it was only possible with Rainbow Tables. Was i wrong?

Technically, yes you are wrong. No hash function is unrecoverable, given enough processing power. The key point, is how much processing power it takes, which in most cases is far bigger than you can imagine. The reason is that the number of possible values increases exponentially at each stage of the hash cycle. For MD5, each stage (there are 64 of them) would multiply the number of possibilities by 10^77 (a lot of zeros). So to successfully reverse an MD5, you'd have to try a really large number of possible permutations (a back-of-envelope calculation shows somewhere on the order of 10^4932 tries). With the fastest super computer ever created today (about 8 petaflops, or 8x10^15 floating point operations per second), you're looking at approximately 10^4908 years to reverse it. Which incidentally is 2.5x10^4898 times the age of the universe right now. Really, it's an enormous number that's beyond our human ability to comprehend...

And that's an absolute best possible case situation.

So technically it is possible to reverse. But practically, no it is not.

In case Rainbow Tables is the only way to go, how someone could reverse a hash that was made with a salt?

The thing is that nobody needs to reverse it. They just need to find a collision. Basically, a collision is two inputs that lead to the same output. So if hash(a) = x and hash(b) = x, a and b are collisions of each other. So, all we need to do is find a collision (which believe it or not is easier than finding the exact input, since there are technically an infinite number of inputs that can give a particular output). With input the size of passwords, typically the collision is the original password.

The easiest way to find this collision is with a precomputed list of hashes (typically called a rainbow table). Basically all you need to do is then look up the hash in the table to see if the original is there. If so, you're done (that easy).

Salts are typically added to combat rainbow tables. This is because if the user enters 1234 as their password, and you use abcdefghijklmnop as the salt, the original would be 1234abcdefgjhijklmnop, which is significantly less likely to appear in a rainbow table. So adding a strong salt will protect against precomputed rainbow tables.

Brute Forcing

However, there is a significant concern if you just do hash(pass + salt). It's not susceptible to precomputed rainbow tables, but it is susceptible to brute forcing. The reason is that cryptographic hash functions (such as sha1, md5, sha256, etc) are designed to be fast. Their traditional role is in Signing, so they need to be fast to be useful. However, in password storage this is the weakness. With modern GPU's, an attacker could brute force (just try every possible password permutation) a simple hash with salt in a matter of hours (for more details, see my blog post about it)...

The best prevention

The best prevention has two features:

  1. It's not easy to pre-compute a table of values (a rainbow table)

  2. It's not fast to hash a single value (not easy to brute force).

As it turns out, there's a simple way of doing that using a hash function. Simply iterate over it and make the output dependent upon a large number of hash functions:

var result = password + salt;
for (var i = 0; i < 10000000; i++) {
    result = hash(result + salt);
}

The key is that by making it artificially slow and using a salt, you're making it resistant to precomputation and brute forcing.

As it turns out, there are 2 standard algorithms that do this (well, use the principles).

The best one is Blowfish hash (bcrypt) which doesn't really use a hash primitive function, but uses the key derivation cycle of the Blowfish cipher. It's available in PHP via crypt(). To use it:

$hash = crypt($password, '$2a$07$' . $salt . '$');

And verify it with

$hash == crypt($password, $hash);

The other method (which is slightly less preferred) is PBKDF2. To program it in PHP:

function pbkdf2($hashFunc, $password, $salt, $iterations, $length = 32) {
    $size   = strlen(hash($hashFunc, '', true));
    $len    = ceil($length / $size);
    $result = '';
    for ($i = 1; $i <= $len; $i++) {
        $tmp = hash_hmac($hashFunc, $salt . pack('N', $i), $password, true);
        $res = $tmp;
        for ($j = 1; $j < $iterations; $j++) {
            $tmp  = hash_hmac($hashFunc, $tmp, $password, true);
            $res ^= $tmp;
        }
        $result .= $res;
    }
    return substr($result, 0, $length);
}

Note:

None of these will protect a user against a very weak password. If they enter a dictionary word, or a common password it will still be likely that an attacker will be able to crack it. They will however add to the defense against moderate strength passwords...

Some more reading:

  • Many hash iterations, append salt every time?
  • Fundimental difference between hashing and encryption
  • MD5 decoding, how they do it
  • The Rainbow Table Is Dead
  • You're storing your password incorrectly
  • Password storage, salt vs multiple hashes
like image 52
ircmaxell Avatar answered Sep 21 '22 14:09

ircmaxell