Double Hashing Passwords for Extra Security?

I sometimes modify certain characters in the MD5 string (e.g. running a few chars through binary XOR (^) with standard char), so that even on the remote chance that someone had DB access, their resulting pass would be completely different.

If you have assumption that your code can not be stolen and/or reverse engineered, why not just encrypt hash and salt with script specific key in CBC mode.

OK i havent read the whole thread but:

Double hashing will NOT make passwords more secure. I cant really go into the maths of it here, but if you are interested, I recommend the book “The numbers behind Numb3rs: solving crime with maths” - and read the chapter on this.

AlienDev, is it online?
I, on other hand, recomend that you read at least Schneiers article.

AlienDev: I’d also love to look at the reasoning. Any other place that explains it all?

Multiple Encryption without salts on each stage are weaker for reasons I explained earlier.

With salts? I don’t think there is any reason not to use them - they don’t put much more processing weight on the server, and they are more secure.

It is somewhat harder to prove that multiple applications of common hashing algorithms make system less secure, as it needs particular algorithm analysis, since it’s not true in a generic case.

But it’s relatively easy to show that it doesn’t make it more secure, regardless of the algorithm, in math language.

Let’s say we deal with m-bit characters and k-bit hashing algorithm. At first, we need to map a character string to number. It can be done like:


n = s[0] * ((2 ^ m) ^ 0) + s[1] * ((2 ^ m) ^ 1) + ... + s[n - 1] * ((2 ^ m) ^ (n - 1))

Then we describe a hashing algorithm as a function: y = f(x), where x ≥ 0.

If we had applied the hashing function once, the range of values we can get is: y1 ∈ [0; 2 ^ k - 1] => |y1| = 2 ^ k.

After next function application, we can get, at most, the same range of values, as we use the same function: y2 ∈ [0; 2 ^ k - 1] => |y2| ≤ 2 ^ k. (The equality – the best case – happens if our discrete function is invertible – there are no two x values in range [0; 2 ^ k - 1], for which f(x) has the same value. And, in that сase, double application of function is not more, not less secure than single.)

From the above we have that |f(f(x))| ≤ |f(x)|. And, using induction (by substitution of x with f(x) on the left side), we get that n’th application of f has power less than or equal to that of f(x).

Yes. While theoretically it is true, the fact is that many rainbow tables exist for single pass md5 hashing, whereas not so many exist for multiple iterations (I imagine less as you go on) so in reality / practically, multiple iterations will be slightly more secure in a real world situation, even if not actually mathematically more secure.

Yes, your correct. But if this was a public available script, either free or by a purchase of a license you would have access to how the hash is applied by default. No one will try to break hashed passwords unless they know how it is created, as it would be close to impossible and would require a lot more processing power. Note. I am thinking on properly created hashes, we all know it is a relativ fast process to create a rainbow table on for example md5 hashes under 50 characters long compared to create one with md5 hashes up to 200 characters.

You are also correct that its impossible to store the failed results into a rainbow table when you also use a public salt (well its possible, but the chance for it beeing efficient is much smaller). But if you have the process behind how the hash is created it is much easier to brute force it when only a public salt is used compared to if you use both a public and a hidden.

For my initial reply that you quoted, I was thinking in regards to that specific piece of code, which was why I mentioned it. Though as you mention, we have an adventage as we have seen the code; but in most cases that is always the case before someone try to brute force hashes.

I am sorry, English is not my first language and sometimes what I type is not exactly what I meant to say.

Weaker was not the correct word for what I was trying to say, as we are talking about hashes not encryptions. What I tried to say was, that the different hashing methods will have different loads when run. I.e. it is faster to run a sha256 hash than a sha512 hash. So in the event you have two different hash types you would first try to brute force the hash which required “less resources to run”.

I am starting to like the idea with two different hashes, and if you alter the way the salt is appended etc it is much stronger. I wrongly assumed that you would use the same method on both, not sure why I did; but that was the case.

Are you storing them in two different columns or do you store them in one column and then just split them before comparing?

I thought we agreed that rainbow tables were not really an issue with a good salt?

Personally I am not worried or scared by the fact that there exist many rainbow tables, Ive tried multiple of them (the largest over 100 GB in size) and Ive not had any other hashes break other than what I would call weak password/salt solutions.

You are doing pretty well from where I was sitting - I didn’t guess you weren’t english!

Yes, but imagine if your site only had the 1 hash, the one that is faster to run. You’d still be happy with the security on it as long as you used a good salt, so adding the other one adds that extra layer of security, and doesn’t take anything away. The main purpose of it is to stop clashes - a rainbow table could come up with something that is quite short but hashes to the same thing using your hashing method, this reduces the risk of that.

2 separate columns, but I don’t think it makes that much of a difference how you do it really.

Yes, I agree, it isn’t an issue with a salt. However, I was trying to answer the original question of is md5(md5()) better than just md5(), and I think it is slightly stronger, in a real world situation. However, nothing beats using a good salt (or 2!) applied properly.

Generally, one of my hashing methods follows this kind of format (although I have made this up on the spot, not copied it from one of my projects, ha!):

$strHash = sha1($strPassword . "%^Q£rgtq3TQ4rner67agw£%NWR&^q253A357a23%FCqw6bawj46...you-get-the-idea" . strrev(md5($strPassword . $strUserSalt . "GAE6jhawe4^Aw4she45^GSD&" . strrev($strPassword))) . "zsw4gawn6SZERYas46" . strrev($strUserSalt) . "taW£%Fawe6nxfgt&*HDrt7hs" . $strPassword);

Basically a complete mess of hashes within hashes, salts, the user salt a couple of times, the password you want to hash, the reverse of that password, reverse of the user salt… all combined in one big hashing method. Noone is going to guess how it is done unless they break onto the server, but then they still have the task of generating rainbow tables for every single user separately, because of the user salt.

Have another method that is something similar, store both and compare both, and you are sorted!

Whats everyones thoughts on this?.

don’t hash but encrypt

assume a key lives on server

a new user signs up and submits their new pwd
append password to key, encrypt pwd and store
like…

$key = “abc…”;
$newKey = $key . $_POST[‘pwd’];
$crypt = new Crypt($newKey);
$encrypted = $crypt->encrypt($_POST[‘pwd’]);
store $encrypted in db

When the user tries to log in do the same but decrypt instead - if decrypted matches submitted pwd then they’re authenticated

  • this way, the encrypted passwords are not crackable with rainbow tables
  • if stolen on their own, the encrypted passwords are very secure
  • if the encrypted pwds are stolen along with the key, they are still very secure
  • if they are stolen with the key and the code that shows the proecess, it would take a brute force attack to crack a pwd - my understanding is that a brute force of that nature would take too long

That is effectively a hashing method though, and rainbow tables can easily be generated for it - although a lot of effort, it is entirely wrong to say they aren’t crackable with rainbow tables.

I’d rather trust one of the established hashing methods like sha1, which have had a lot of research done into them and are fairly secure, rather than a hashing method I made myself when I have no idea about the security of it.

My understanding of rainbow tables is that they work on something like md5 because the hash is always the same for the given input. In this case, the encrypted output that gets stored is not the same each time the input goes through the encryption process.

I’d rather trust one of the established hashing methods like sha1, which have had a lot of research done into them and are fairly secure, rather than a hashing method I made myself when I have no idea about the security of it.

Just to clarify, I generally use Blowfish - so it’s not something I made myself and I do know it is secure.

The first paper I mentioned comes to conclusion that you can use encryption algorithm for this.
The reason for doing such an resource intensive password expansion is to slow down dictionary attacks, as you can see for expansion that uses N iterations it is slowed down exactly N times (provided that hash function used or encryption algorithm used are with desired cryptographic properties) as compared with one iteration case.

If we look at graph of simple hash function H(x), that has codomain={A…L}
We see that H(H(H(H(A))))=E.

Now the problem with simple multiple hashing is that overall structure for given hash function remains constant. That way it is feasible to maintain dictionary tables for multiple iterations of this hash function. The picture changes a lot if we add fixed salt=s in every iteration (shown with green arrows):

Because of fact that while A is member of subdomain domB, for witch H(domB)=B, the string A+s is not necessarily a member of this subdomain. So effectively the graph for H(X+s) where s is salt looks like this:

The good thing is that we can expect this sequence to change with every different salt value. The bad thing is that nobody has really investigated, how pretty these graphs form in reality.

Its a ‘real’ book; sorry not online. Only place I’ve read that explains it well.

AlienDev, ok, will try to get that book one way or another. Any comments on how it contradicts the paper I was refering to?

ophcrack and rainbow tables will take care of that password very quickly and effortlessly. What you need to make people’s lives more difficult is salt as was mentioned before. The hacker then needs to find the salt and calculate rainbow tables based on that which may take quite a while. What is often overlooked however is that in most cases cracking passwords isn’t necessary for intrusion at all. Many security holes allow attackers to roam around freely and happily in your system without ever bothering with your password at all.

To be honest, if someone has access to your administration / database - password encryption isn’t going to be the biggest problem.

There are many way to create a practically unbreakable encryption. Especially if they don’t know your method, e.g:

$password = 'Password123';
$salt = 'fni021f';
echo MD5(~MD5($password) . $salt . MD5(~$password . ~$salt));

Unexpected bitwise operators can be a godsend when it comes to encryption.

You should buy this book http://phpsecurity.org/

double hashing is a waste of time.