Jump to content

Question

Posted

I've had this thought for a while - but always figured there was a reasonable solution to it.

 

I run a CMS system that currently hashes its passwords into MD5 and then into SHA1 passwords - or SHA256, depending on the system.

I've always thought why can't you hash passwords a lot, to make them more secure.

 

For example:

<?php
$password = 'ilovepassword1';
$securepass = sha1(md5(md5(sha1(md5(sha1($password))))));

echo $securepass;
?>

Apart from it being totally stupid, and inefficient - why isn't this a 'proper' solution?

 

Surely to crack it, you'd have to crack every layer- in the example above, 6 layers?

 

 

Would love an answer!

 

 

Tim

Share this post


Link to post
Share on other sites

56 answers to this question

  • 0

Posted

Wow guys - seems like there are lots of mixed opinions on this one!

 

I've never looked into Salting passwords before, so start implementing salts now.

 

From what I understand, a Salt is a 'unique' phrase appended onto the end of a password, e.g.

sha1($password+$salt)

So what if I still multiple hashed that?

(md5(sha1($password+$salt))

Or what if I added a different salt everytime?

md5(sha1($password+$salt)+$salt2)

Share this post


Link to post
Share on other sites
  • 0

Posted

Wow guys - seems like there are lots of mixed opinions on this one!

 

I've never looked into Salting passwords before, so start implementing salts now.

 

From what I understand, a Salt is a 'unique' phrase appended onto the end of a password, e.g.

sha1($password+$salt)

So what if I still multiple hashed that?

(md5(sha1($password+$salt))

Or what if I added a different salt everytime?

md5(sha1($password+$salt)+$salt2)

 

To be honest you're better off just using an algorithm that implements a salt, key stretching and adjustable iterations at its core (e.g. bcrypt or scrypt).

 

Using a salt, sha1($password . $salt), will prevent people looking up the hashes in any existing rainbow tables, but if your server has been compromised the attacker will probably obtain your salt(s) too, meaning they can still brute force most of the passwords. A single modern GPU can generate 3 billion SHA1 hashes per second, in less than a week you could brute force all 8-character passwords (character set: 0-9A-Za-z!$%&*+,-.:;^_`~<>?@) unless you use a different salt per-password, multiple hashing won't prevent this either. 

 

BCrypt on the other hand is arbitrarily slow, giving you a compromise between security and speed (you can adjust the iteration count). Even a modern GPU (or CPU) will only be able to calculate around 20 hashes per second making brute-forcing non-dictionary words effectively useless, unless the attacker has unlimited funds. 

 

SHA1 (and other quick hashing algorithms) are good for verifying data integrity, but less than ideal for storing passwords. The relative calculation speed of SHA1/MD5 make them a perfect target for brute forcing.

1 person likes this

Share this post


Link to post
Share on other sites
  • 0

Posted

Your assumption that such hashes have to be cracked one layer at a time MUST be based on an presumption that an attacker will have no knowledge of your algorithm (your choice of which hash functions are used and how they are chained, etc) and will be unable to determine it. In theory and based on this presumption: In terms of an attacker using lookup tables, when they lookup a hash they would find that the result is a string that's not the password itself but instead the hash from the parent hashing function. They would then need to look that up, and so on until they eventually get to the actual password. There is an inefficiency of having to do multiple lookups, but more crucially for this to actually work in practice, in order to actually be able to perform these lookups, the attacker would require lookup tables that cover the hashes of all possible hashes. Such tables cannot exist because they would require a vast amount of disk space to store. Only two chained hash functions could therefore actually suffice here to block lookup attacks.

You cannot rely upon this presumption though. If we assume that an attacker does somehow know the algorithm, then with a lookup table based attack, the attacker can compile lookup tables based on your specific algorithm prior to then attempting an attack on the stolen hashes. Understand that hashing algorithms are designed to be quick, so throwing in a few extra function calls isn't really going to significantly impact an attacker generating them. Furthermore in relation to brute-force/dictionary based attacks against an offline copy of the hashes, the impact of your algorithm in terms of speed of execution is going to be negligible.

Xinox and Asik also raised some excellent additional points earlier.

Just want to correct myself on a point I made here in regards to hashes of hashes in lookup tables and iterative lookups. MD5 produces a 128-bit output so there are 2^128 (3.40282366920938463463374607431768211456
1 person likes this

Share this post


Link to post
Share on other sites
  • 0

Posted

Assuming you can check 1 million hashes per second

 

On what, a commodore 64? Your example is a little behind the times here.

Share this post


Link to post
Share on other sites
  • 0

Posted

I disagree with your simple notion that the key to encryption is to not rely one thing on another; in cryptography this seems to me to be prevalent. Most if not all crypto relies on the discreet logarithm problem for instance. HTTPS relies on both public-key (asymmetric) and symmetric crypto. I could go on, but I'm just nit-picking :p

 

The more secure things are, the more obfuscated they are. Thats really what crypto is. obfuscation.

Share this post


Link to post
Share on other sites
  • 0

Posted

Just as a matter of interest, the idea of password generating is that every time the password is entered, it generates the same hash. With a "random"  salt as random as a preset salt, just random to those that don't know it.

So how would one have a fully random salt which generates a different hash each time that can actually be used?

Or this in the trend of hash(password+salt+password/username) ? Cause I cant see it working if it isn't easily reproduceable.

 

I personally made my own hashing function using a little used encryption method Whirlpool together with from what I think is a lesser used sha, as it  usually seems sha1, 256 or 512 and im going with 384 as I'm hoping it helps being a bit unpredictable in the hashes you use.

Share this post


Link to post
Share on other sites
  • 0

Posted

Just as a matter of interest, the idea of password generating is that every time the password is entered, it generates the same hash. With a "random"  salt as random as a preset salt, just random to those that don't know it.
So how would one have a fully random salt which generates a different hash each time that can actually be used?
Or this in the trend of hash(password+salt+password/username) ? Cause I cant see it working if it isn't easily reproduceable.
 
I personally made my own hashing function using a little used encryption method Whirlpool together with from what I think is a lesser used sha, as it  usually seems sha1, 256 or 512 and im going with 384 as I'm hoping it helps being a bit unpredictable in the hashes you use.

I'm finding it a little hard to follow you, but I'll try and respond...
When a user registers a new account on your web application, they provide their desired username and password. You should use a secure CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) in the generation of a salt. You hash the password and the salt together to encrypt the provided password. This could be done something like the following:
$salt = bin2hex(mcrypt_create_iv(20, MCRYPT_DEV_URANDOM));
$passwordHash = hash('sha256', $password . $salt);
You would then store the salt and the hash in the database. A good suggestion made here is that you might like to store the hash method too (and if using PBKDF2/bcrypt the number of iterations also), which will help in getting your application to cleanly handle migration to a different hash function (and/or alternate number of iterations) at a future date. You could concatenate these pieces of data together as a string in the form of HashMethod:Salt:Hash and store it in a single field in the database table if you wished.

The salt above has been generated with a cryptographically secure random generator and it is unique to that user. If the user's password is ever changed, you can generate a new salt for them.

Your own hashing algorithm involving chaining of whirlpool and sha384 is precisely the same kind of thing this entire thread has been discussing. It is doing very little to nothing at all to enhance your security. Furthermore the idea of hiding behind the "lesser used" sha384 in the hope of being "unpredictable" is frankly ridiculous, I'm sorry but it is :/

Share this post


Link to post
Share on other sites
  • 0

Posted

I'm interested in N_K's challenge. So usually, it's to be assumed that the rules of passwords are known. If passwords are limited to something like alphanumerics of 8 characters or less, then it's not too hard...

 

52 possible characters (upper and lower), 10 possible digits, and length of 0 to 8 means there are at most 62^8 tasks to carry out (basically the comparison, MD5(MD5(PasswordGuess)) == KnownHash). Sure, 200 trillion of those sounds like a lot, but

MD5 is popular because it is not slow. Fast implementations take advantage of SSE or even better, CUDA, which means you can generate hundreds of millions keys per second. Some rough math shows that (depending on your hardware), it is possible to go through all 200 trillion in less than a week.

 

Still I wouldn't trust my own coding skills to create a program that's really that fast :P

Share this post


Link to post
Share on other sites
  • 0

Posted

I'm interested in N_K's challenge. So usually, it's to be assumed that the rules of passwords are known. If passwords are limited to something like alphanumerics of 8 characters or less, then it's not too hard...

 

52 possible characters (upper and lower), 10 possible digits, and length of 0 to 8 means there are at most 62^8 tasks to carry out (basically the comparison, MD5(MD5(PasswordGuess)) == KnownHash). Sure, 200 trillion of those sounds like a lot, but

MD5 is popular because it is not slow. Fast implementations take advantage of SSE or even better, CUDA, which means you can generate hundreds of millions keys per second. Some rough math shows that (depending on your hardware), it is possible to go through all 200 trillion in less than a week.

 

Still I wouldn't trust my own coding skills to create a program that's really that fast :p

 

Indeed, a single high-end GPU (7970) can generate/compare around 6 billion MD5 hashes per second, worst case 3 billion of md5(md5(text)) per secondif you were to assume the password was alpha-numeric of only 8 characters it would only take (62^8 + 62^7 + 62^6 + 62^5 + 62^4 + 62^3 + 62^2 + 62) / (3 * 10^9) seconds ? 20.5 hours. So yeah, if it was 8 alpha-numeric characters or less you could definitely crack it in less than a week (or a day even).

 

Also, since services like Amazon EC2 offer on-demand access to servers with high-end GPUs priced at only $2/hour you could do it much quicker too by simply spinning up a few instances for an hour or two. 

Share this post


Link to post
Share on other sites
  • 0

Posted

52 possible characters (upper and lower), 10 possible digits, and length of 0 to 8 means there are at most 62^8 tasks to carry out (basically the comparison, MD5(MD5(PasswordGuess)) == KnownHash). Sure, 200 trillion of those sounds like a lot, but

MD5 is popular because it is not slow. Fast implementations take advantage of SSE or even better, CUDA, which means you can generate hundreds of millions keys per second. Some rough math shows that (depending on your hardware), it is possible to go through all 200 trillion in less than a week.

 

Out of curiosity, I just checked what rate my 5yo computer can compute md5(md5()) at with hashcat, and it was 3GHash/sec. With a newer GPU, I imagine you could compute them at least 2x faster.

Share this post


Link to post
Share on other sites
  • 0

Posted

Err, no.

 

facepalm.png

Share this post


Link to post
Share on other sites
  • 0

Posted

Even worse than that, you guys just calculated the full compute time.

 

Most attacks begin with dictionaries that will obtain 70% or so of passwords and take about an hour to run. On top of that, chances of your password laying at the very end of the that 20.5 hour run are (on average) nearly 0.

 

MD5 is a fast password hash. It's not something you should be using for storing passwords. The same is true of SHA1. If you are looking to hash passwords, you should be using bcrypt or one of the other slow chain hash methodologies.

 

Also, salting doesn't note-worthily increase the compute time for a single password. The benefit of hashing is that you need to recalculate the hashes for every single user name (due to their differing salts).

 

Running MD5 repeatedly, or chaining multiple algorithms only helps you in increasing the compute time, in which case there are better ways to do it >.< When I was starting Crypto at uni, I wondered that myself. The simple answer is that you must at all times assume that an attack is aware of how the encryption scheme works. Security through obscurity (that is hiding how the scheme works) is not security at all. You need it to be publicly known and computationally impractical to attack.

 

Yep..


Out of curiosity, I just checked what rate my 5yo computer can compute md5(md5()) at with hashcat, and it was 3GHash/sec. With a newer GPU, I imagine you could compute them at least 2x faster.

So much worse than that if you have a dedicated chip. There's a dedicated MD5 hashing chip that will scream through them about 200 times faster than that >.<

Share this post


Link to post
Share on other sites
  • 0

Posted

Yeah, I was playing around with hashcat last night and I was getting around 1.6 billion MD5 hashes a second on my GTX 570, and that was probably with bad settings.

With the double MD5 case I was only getting 600 million hashes a second.

...
To be clear, salting does NOT "defeat" rainbow tables in any case, it simply requires new ones be generated that incorporate the salt in the computation.

Using usernames for salts isn't a great idea. Usernames are reused and may be publicly known, reducing lookup-table storage requirements for an attacker and allowing them to pre-compute lookup tables in advance of breaching a database. With random salts, which an attacker should presumably only gain access to at the same time as the hashes, i.e. upon breaching the database, lookup-tables must be generated at that point and passwords cracked before the breach is discovered and passwords changed. Using the username as a salt isn't terrible, but its not as good as a proper random salt.
...


What I meant by "defeating" rainbow tables, was that you'd have to re-generate the table for each user (and only that user), so you're spending a lot of time pre-generating a single use dataset, when you could just compare the hashes as you're generating them against the hash you have instead (So if you hit a match, you don't waste time by generating the rest of the table)

Although with my earlier comment about GPU based hash computation, maybe that isn't such a big deal.

Question though, what makes a random per user salt stronger than salting with the username? Is it just that the username would contain "less randomness" compared to a random salt? You're storing them both in the database so I don't see that as the weakness.

Share this post


Link to post
Share on other sites
  • 0

Posted

Question though, what makes a random per user salt stronger than salting with the username? Is it just that the username would contain "less randomness" compared to a random salt? You're storing them both in the database so I don't see that as the weakness.

 

I don't think there is any significant difference. They accomplish the same goal of having a unique salt per user account.

Share this post


Link to post
Share on other sites
  • 0

Posted

The more secure things are, the more obfuscated they are. Thats really what crypto is. obfuscation.

uh... what? guess you've never heard of one-time pads...

 

I don't think there is any significant difference. They accomplish the same goal of having a unique salt per user account.

does length or entropy matter for a salt given that it's known anyway?

Share this post


Link to post
Share on other sites
  • 0

Posted

does length or entropy matter for a salt given that it's known anyway?

 

One of the desirable traits of hash algorithms is that small changes to the input will result in seemingly unpredictable changes to the output. The two hashes for "abc" and "abc1" will look just as different from each other as the hashes for "abc" and "abc2". So the 'randomness', length, or any other quality of the salt shouldn't make a difference, so long as the same salt isn't repeatedly used. Obviously, though, in other cryptographic scenarios, entropy and length of keys does play a big part in security.

Share this post


Link to post
Share on other sites
  • 0

Posted

<snip - palm-face image a bit large...>

Let me give you a better reply :p (Though I'm just going to be repeating myself a bit and I'm not sure you're actually after one...)
...>

You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!

Yes, we know that an md5 hash is exactly 32 characters long and made up of hexadecimal digits only (case in-sensitive), i.e. it's 128-bits long. Knowing this does not help us at all though in doing a reverse iterative lookup with lookup/rainbow tables to get to the first hash, as I've already pointed out. There are 2^128 (3.40282366920938463463374607431768211456

Share this post


Link to post
Share on other sites
  • 0

Posted

One of the desirable traits of hash algorithms is that small changes to the input will result in seemingly unpredictable changes to the output. The two hashes for "abc" and "abc1" will look just as different from each other as the hashes for "abc" and "abc2". So the 'randomness', length, or any other quality of the salt shouldn't make a difference, so long as the same salt isn't repeatedly used. Obviously, though, in other cryptographic scenarios, entropy and length of keys does play a big part in security.

I understand what you're saying and don't necessarily disagree with you, but in most cases, there simply isn't any good reason to compromise on security. It often comes down to laziness or incompetence. When a web service stores user passwords without salt (or even worse, as plain text), it makes you question the quality of their service as a whole.

 

In the end, it really is best to stick to standard cryptographic protocols rather than making up your own. Do a little research into the encryption used by MEGA to understand why; you'll find that security researchers quickly pointed out several issues with it.

Share this post


Link to post
Share on other sites
  • 0

Posted

Is bcrypt hashing secure?

Share this post


Link to post
Share on other sites
  • 0

Posted

Is bcrypt hashing secure?

If you use a secure, random salt: yes, probably one of the most secure mainstream solutions there is.

Share this post


Link to post
Share on other sites
  • 0

Posted

Just another tip, hiding your password creation and verification routines isn't a bad idea.

 

I like to use used an encrypted stored procedure in the database server for logins(In my case MSSQL). You feed it the user name and password, it returns true or false. You can, of course, get more complex, but the design rule was that all logins are validated through the one procedure. You can call it from another proc, from the web server or from any other front end, but that SP was the only way to validate a login.

Share this post


Link to post
Share on other sites
  • 0

Posted

From what I can tell: Multiple hashing a password DOES make it more secure, but only marginally.

 

It's MORE efficient and secure to use more complex hashing methods, like bcrypt and salts.

 

Am I correct?

Share this post


Link to post
Share on other sites
  • 0

Posted

From what I can tell: Multiple hashing a password DOES make it more secure, but only marginally.

 

It's MORE efficient and secure to use more complex hashing methods, like bcrypt and salts.

 

Am I correct?

You should be using salts no matter what you do. But yes, something like bcrypt or a PBKDF solution would be better than using regular hashing methods.

Share this post


Link to post
Share on other sites
  • 0

Posted

From what I can tell: Multiple hashing a password DOES make it more secure, but only marginally.
 
It's MORE efficient and secure to use more complex hashing methods, like bcrypt and salts.
 
Am I correct?

"Multiple hashing" being more secure - a little bit, yes.

More efficient and secure to use methods like bcrypt and salts - yes and no. Yes, salts absolutely enhance security. Yes, bcrypt (or PBKDF2) is going to be a more secure choice. No, bcrypt (or PBKDF2) are not going to be more efficient, it will require more processing power (on the part of both yourself and an attacker).

My advice again:
  • Stop trying to come up with odd hashing algorithms like this, they're not going to help you at all.
  • Stop using md5/sha1, at least use sha256 or preferably in some cases PBKDF2/bcrypt.
  • Do use a salt and use a different one for each user.

Share this post


Link to post
Share on other sites
  • 0

Posted

Just another tip, hiding your password creation and verification routines isn't a bad idea.
 
I like to use used an encrypted stored procedure in the database server for logins(In my case MSSQL). You feed it the user name and password, it returns true or false. You can, of course, get more complex, but the design rule was that all logins are validated through the one procedure. You can call it from another proc, from the web server or from any other front end, but that SP was the only way to validate a login.


I can't imagine that being very secure, if somebody attacks your database (Which is pretty much going to be the attack vector) they've then got your custom method for authenticating users.

If the method was properly secure, you could tell the attacker exactly how you're doing it and they still wouldn't be able to break it (Just because the attacker knows you're using bcrypt, doesn't make bcrypt any less secure, etc.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.