I know MD5's safety is under question lately and this is the reason a lot of people are using salt (I dont understand this at all btw) but I was wondering if you wanted to easily implement a safe system in php can you just md5 something twice?
like test > 098f6bcd4621d373cade4e832627b4f6 > fb469d7ef430b0baf0cab6c436e70375
So basically:
$val = 'test';
$val = md5($val);
$val = md5($val);
Would that solve the whole rainbow security stuff? Is there an easy/noob proof way of making secure database passwords in php?
Hashing twice makes little real sense and doesn't accomplish much. In general, however, multiple hashing can make some sense. For example, if you hash enough times to take something like 100 ms (or so, depending on hardware) it can help a little. The basic idea of it is pretty simple: adding 100 ms to a normal login is a barely noticeable delay -- but if you're trying to build something like a table for a dictionary attack, multiplying the time by something like a thousand (or whatever exactly it works out to) starts to make a real difference -- a table that you could normally compute in (say) a day, takes a few years instead. That's enough difference that anything but really serious attackers will often give up (or just get bored) long before they finish the job.
Salt is an entirely separate tool. Using it does not make up for weakness in the underlying hash function. The idea here is that the size of a table for a dictionary attack becomes substantially larger (e.g., for a one-byte salt, 256 times larger). The salt is not normally kept secret, but it's relatively random, so an attacker who's doing a dictionary attack can't just hash each word as-is, but has to take each possible salt value into account. At the risk of repetition: it deals with a weakness in how (most) people pick passwords, not any weakness in the hash function itself.
If you don't believe in MD5, you can try a higher algorithm by using the hash() function:
$hash1 = hash('sha1', 'The string to hash by SHA-1');
$hash2 = hash('sha256', 'The string to hash by SHA-256');
$hash3 = hash('sha512', 'The string to hash by SHA-512');
$hash4 = hash('ripemd160', 'The string to hash by RIPEMD-160');
In my opinion it does not make sense to hash twice.
EDIT: Fixed typo in last line of code.
Whether or not you use the MD5 algorithm...
No, an attacker can always have two rainbow tables (one for the extra level of hashes, and one for the passwords). And from another answer of mine:
[...] it still just requires the password and nothing more to crack. In other words, you are just applying the hashing functions to the same thing a few times more.
You use a salt to make it more difficult for the attacker to get at your passwords, because then he would need to know the salt so that he can use it in computing the hashes for your passwords.
Storing passwords securely is tricky, most the advice posted here is not accurate. So I will defer to Thomas Ptacek's widely cited post on the subject: http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html
For the record, I evaluated that
$val = 'test';
$salt='somerandom!!aa##9900';
$val = md5($salt.$val);
$val = md5($val);
Its pretty safe. The secret is in the salt.
However, md5 is short so the chances of concurrences are "high" (one in 1.208.925.819.614.629.174.706.176 = 32^16, 32 words with an hexadecimal each one)
Related
So I know that MD5's are technically a no-no in new applications, but I randomly had a thought of this:
Since
md5($password);
is insecure, wouldn't
md5(md5($password))
be a better alternative?
would it keep getting more secure the more I use it? Say if I made a function like this
function ExtremeEncrypt($password)
{
$encryptedpass = md5(sha1(md5(md5($pass))));
return $encryptedpass;
}
Would this function be a good alternative to say using a random salt for every account like vbulletin does.
Double hashing a string does nothing except limit your key space and make collisions more likely. Please don't do this. Double md5 hashing is actually less secure than a single hash with some attack vectors.
A better option would be to use the password_hash function in php 5.5 or ircmaxell's password_compat library for earlier php versions.
First of: hash and encryption are not the same. Hash is a one-way function while encryption expects data could be decrypted.
You should not try to invent your own solution when it comes to security. In PHP, since 5.5 version, there is native solution called Password Hashing. md5() is insecure and you should be aware of that.
If you have PHP below 5.5 version, you should use salt to hash & store your passwords.
You have lots of answers here and they are accurate but they don't really explain why.
MD5 is a hashing algorithm. What a Hashing algorithm does, is take a long piece of data and analyse it cryptographically in a way that creates a smaller piece of data. So from ABCDEFGHIJKLMNOPQRSTUVWXYZ with my custom hash algorithm I might create a single digit hash 5.
When that is done, you lose information - ABCDEFGHIJKLMNOPQRSTUVWXYZ contains far more information than 5 and there is no way to make the translation the other way.
The problem with hashing in a way that only allows an outcome of 0-9 ( this is effectively a Checksum ) is that if you take two pieces of text, the chances are quite high that they will have the same hash. So maybe with my algorithm ZZZZZZZZZ will also produce a hash of 5. This is what is termed a Hash Collision.
Now what happens if I take the hash of my hash? Well, my starting point is already very low information - the most it can possibly be is one of ten digits, so the chance of a collision is now exceedingly high. Supposing when my hash algorithm runs on numbers it returns 1 if it is odd and 0 if it is even- so if I have a hash of ABCDEFGHIJKLMNOPQRSTUVWXYZ which comes to 5 then I have a 10% chance of a collision. But if I make a hash of that hash, I will now have a 50% chance of a collision.
The trick of cryptography is hiding information in such an enormous possible space that it is unbelievably hard to find. The more you shrink that possible space, the less well hidden your information is.
Short answer: No.
md5 is easy to break using brute-force. Adding additional layers of hashing only slows down a brute-force attack linearly.
First of all md5 isn't really encryption, because there isn't a decryption method to it. It's called hashing.
The standard practice is to salt your passwords:
$salt = [some random/unique number, people usually use user_id or timestamp]
$hashed_password = sha1($salt . $password)
Remember that you need to know the salt, hence usually it means storing it along with the hashed password.
You can have multiple salts, and arrange them however you like.
I'm reading so much conflicting advice as to how to store passwords securely. All I know for sure is not to use MD5! I've seen people advocate using PHP's bcrypt function, which seems like it'd hog the server's processor. I've seen advocates for salts, and advocates for not using salts.
It's all just so unclear. Is there real and credible advice as to how to store passwords securely?
Edit: After a fair amount of research, I found an article from ;login: that deals with the topic in quite some depth: http://www.usenix.org/publications/login/2004-06/pdfs/alexander.pdf
Well, there is several parts to this.
You need to try to make it difficult to get to your db and passwords in the first place, keep them secure. This includes not making your passwords cleartext and not using a symmetric encryption algorithm.
You need to use a salt. Doing this prevents people from using a precomputed lookup table (i.e. rainbow table) or something like http://md5.rednoize.com/. Pick some data for your salt that is both unique and unpredictable. I usually use a random 32 bit value, but I wouldn't go much less.
Some algorithms are stronger than others. This is defined in a couple ways
How fast it can be computed. Longer is better. The faster the attacker can calculate hashes, the better the odds are for a bruteforce attack.
If the algorithm has no known weakness which reduce the search space. For example, the number of bits in an md5 hash is misleading because there are known attacks that reduce the actual search space
As of today I think SHA1 or SHA2 with a salt is reasonably secure for the near future. There is a utility called bcrypt which uses an asymmetric variant of blowfish and has the concepts of salt and computational expense built-in, it might be worth checking out.
Edit: I wanted to clarify what a salt is, as there is a lot of misconception about it on SO and online.
What a Salt is not
A secret, pre-agreed upon string that you hash with the password. This is a secret key, not a salt.
What a Salt is
You include the salt (unique and unpredictable per hash) along with your password when hashing, but you also include a unencrypted copy of it outside of your hash, so that when verifying the hash later you are able to include the same salt when given a test password before hashing it so you can properly compare the hash.
The point of bycrpt is to hog the processor! (Relatively speaking.) It is for this reason that it is "better" for password hashing than SHA1/2. (This "better" assumes that the password hashes are already in the hands of the attacker or otherwise exposed; while it would nice if it were not the case, even big corporations have had security compromises.)
This requirement was explicitly considered for bcrypt -- if you can only process 1k hashes a second (still, that's a good bit of log-in attempts), how long will that take an attacker to brute-force? A good bit longer than if they could process 10 million hashes a second! The target attack space of a brute-force that is only of the allowed password input, which is often much smaller -- esp. in practice with "simple passwords" -- than the space of the hash!
And a salt is very much required to avoid rainbow tables which trade time for space :) A rainbow table would effectively need to be created for each unique salt value. (Thus, the more unique salt values, the more space is required and with enough values this becomes impractical for an attacker.)
Happy coding.
First of all you need to use a good hash function, I suggest SHA-256. You can create a SHA-256 hash like this:
$hash = hash('sha256', $password);
In addition you could also use salting like this:
$salt = 'salt here';
$hash = hash('sha256', $salt . $password);
Moreover, you can use HMACs, like this:
$secret = 'your secret';
$hmac = hash_hmac('sha256', $password, $secret);
The best way to create solid hashes is through salting and iteration.
You should loop the above functions until hashing takes 200ms.
You could also go ahead and use encryption, but that would be a bit overkill for most situations.
This is similar to this question: Methods for storing login information in database
Credible advice: Never store your passwords in clear text!
Beyond that you have some choices to make. As I mentioned in the response to the linked question, there are two camps: let some else store your authentication data or do it your self. If you decide to do it your self, then you need to come up with a hashing routine. This should probably include a salting your passwords.
You can use sha256. A good thing to do is to add extra information to the password such as username, userid, or some other data to it. This way, if someone hack your database, it will be impossible to use an existant hash database to find the password. They will have to crack the password starting from zero.
I'm looking at some code that I have not written myself. The code tries to hash a password with SHA512 and uses just time() as the salt. Is time() too simple a salt for this or is this code safe?
Thanks for the answers and comments. I will sum it up here for the new readers:
salt should be different for each user, so if 2 users register at the same time, their salts won't be unique. This is a problem, but not a big one.
but salt shouldn't be in any way related to the user, so time() is not a good salt.
"Use a random, evenly distributed, high entropy salt." -- That's a mouthful, so what code could possibly generate a random, evenly distributed, high entropy salt?
Ok, so how about I replace time() with a random string 32 char long. The random string could be generated from looping 32 times over a set of alphabet chars. Does that sound good?
Short answer:
No, time() is not a good salt.
Long answer:
copied from my answer to Salt Generation and open source software
What is a salt?
A salt is a random set of bytes of a fixed length that is added to the input of a hash algorithm.
Why is salting (or seeding) a hash useful?
Adding a random salt to a hash ensures that the same password will produce many different hashes. The salt is usually stored in the database, together with the result of the hash function.
Salting a hash is good for a number of reasons:
Salting greatly increases the difficulty/cost of precomputated attacks (including rainbow tables)
Salting makes sure that the same password does not result in the same hash.
This makes sure you cannot determine if two users have the same password. And, even more important, you cannot determine if the same person uses the same password across different systems.
Salting increases the complexity of passwords, thereby greatly decreasing the effectiveness of both Dictionary- and Birthday attacks. (This is only true if the salt is stored separate from the hash).
Proper salting greatly increases the storage need for precomputation attacks, up to the point where they are no longer practical. (8 character case-sensitive alpha-numeric passwords with 16 bit salt, hashed to a 128 bit value, would take up just under 200 exabytes without rainbow reduction).
There is no need for the salt to be secret.
A salt is not a secret key, instead a salt 'works' by making the hash function specific to each instance. With salted hash, there is not one hash function, but one for every possible salt value. This prevent the attacker from attacking N hashed passwords for less than N times the cost of attacking one password. This is the point of the salt.
A "secret salt" is not a salt, it is called a "key", and it means that you are no longer computing a hash, but a Message Authentication Code (MAC). Computing MAC is tricky business (much trickier than simply slapping together a key and a value into a hash function) and it is a very different subject altogether.
The salt must be random for every instance in which it is used. This ensures that an attacker has to attack every salted hash separately.
If you rely on your salt (or salting algorithm) being secret, you enter the realms of Security Through Obscurity (won't work). Most probably, you do not get additional security from the salt secrecy; you just get the warm fuzzy feeling of security. So instead of making your system more secure, it just distracts you from reality.
So, why does the salt have to be random?
Technically, the salt should be unique. The point of the salt is to be distinct for each hashed password. This is meant worldwide. Since there is no central organization which distributes unique salts on demand, we have to rely on the next best thing, which is random selection with an unpredictable random generator, preferably within a salt space large enough to make collisions improbable (two instances using the same salt value).
It is tempting to try to derive a salt from some data which is "presumably unique", such as the user ID, but such schemes often fail due to some nasty details:
If you use for example the user ID, some bad guys, attacking distinct systems, may just pool their resources and create precomputed tables for user IDs 1 to 50. A user ID is unique system-wide but not worldwide.
The same applies to the username: there is one "root" per Unix system, but there are many roots in the world. A rainbow table for "root" would be worth the effort, since it could be applied to millions of systems. Worse yet, there are also many "bob" out there, and many do not have sysadmin training: their passwords could be quite weak.
Uniqueness is also temporal. Sometimes, users change their password. For each new password, a new salt must be selected. Otherwise, an attacker obtained the hash of the old password and the hash of the new could try to attack both simultaneously.
Using a random salt obtained from a cryptographically secure, unpredictable PRNG may be some kind of overkill, but at least it provably protects you against all those hazards. It's not about preventing the attacker from knowing what an individual salt is, it's about not giving them the big, fat target that will be used on a substantial number of potential targets. Random selection makes the targets as thin as is practical.
In conclusion:
Use a random, evenly distributed, high entropy salt. Use a new salt whenever you create a new password or change a password. Store the salt along with the hashed password. Favor big salts (at least 10 bytes, preferably 16 or more).
A salt does not turn a bad password into a good password. It just makes sure that the attacker will at least pay the dictionary attack price for each bad password he breaks.
Usefull sources:
stackoverflow.com: Non-random salt for password hashes
Bruce Schneier: Practical Cryptography (book)
Matasano Security: Enough with the Rainbow Tables
usenix.org: Unix crypt used salt since 1976
owasp.org: Why add salt
openwall.com: Salts
Disclaimer:
I'm not a security expert. (Although this answer was reviewed by Thomas Pornin)
If any of the security professionals out there find something wrong, please do comment or edit this wiki answer.
As for what seems to be a good source for your random salt
Also read: What is the most secure seed for random number generation?
In the absence of dedicated, hardware based, random generators, the best way of obtaining random data is to ask the operating system (on Linux, this is called /dev/random or /dev/urandom [both have advantages and problems, choose your poison]; on Windows, call CryptGenRandom())
If for some reason you do not have access to the above mentioned sources of random, in PHP you could use the following function:
From the source of phpass v0.3
<?php
/**
* Generate pseudo random bits
* #copyright: public domain
* #link http://www.openwall.com/phpass/
* #param int $length number of bits to generate
* #return string A string with the hexadecimal number
* #note don't try to improve this, you will likely just ruin it
*/
function random_bits($entropy) {
$entropy /= 8;
$state = uniqid();
$str = '';
for ($i = 0; $i < $entropy; $i += 16) {
$state = md5(microtime().$state);
$str .= md5($state, true);
}
$str = unpack('H*', substr($str, 0, $entropy));
// for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!?
// so, added the substr
return substr(str_pad($str[1], $entropy*2, '0'), 0, $entropy*2);
}
?>
Updated
It's not a really good salt, but probably good enough to defeat all but the most determined and resourceful attackers. The requirements for a good salt are:
Different for each user
long enough (at the very least alphanumeric 8 characters) to make the concatenation of salt and (potentially weak) password too long for a brute force attack.
time() values are not really long enough, since they have 10 characters, but only digits.
Also, sometimes two users may get the same value when they are created within the same second. But that's only a problem if you have situations where many users are automatically created within the same second.
In any case, far more important than a perfect salt is using a good hash function, and SHA512 is one of the best we have available right now.
This post may veer a little too far away from your original question, but I hope you find it useful;
Security is about raising barriers and hurdles; defence in depth. There is no truly secure hashing solution, just ones that are hard to break. It's like putting in a burglar alarm and window locks in your house - make your site less attractive to break into than someone else's.
Salt for a crypt algorithm is only a small part of the security problem. A single salt simply means that there is one less thing to figure out when trying to break the password for multiple users. A low-entropy salt (such as the server's time) makes it a little bit harder, and a high-entropy salt makes it harder still. Which of these to use, and whether it's something you need to worry about primarily depends upon both the sensitivity of the data you're protecting, but also what other security measures you have in place. A site that just gives a personalised weather forecast for a selected city obviously has less sensitive data than one which has your home address, mother's maiden name, date of birth and other info which could be used for identification purposes.
So here's the rub; a high entropy salt is still a bad salt if it's easily obtainable.
In the real world, storing a salt in the database (random or not) is probably less secure than using a constant salt and burying it away from private eyes in a file inaccessible via the web browser. Whilst a unique and high entropy salt is harder to guess, if you've allowed root login from any server on MySql and set the password to 'password' it doesn't really matter! Constrast how easy it is to crack the database versus getting a valid login to your server - which is possibly more difficult to do discretely as you can put fail2ban and a plethora of other attack vector watchers in place depending upon your setup.
You can combine the two approaches by storing the location of a file containing a user-specific salt in the database, rather than the salt itself. Whether having to crack both the file system and the database is warranted depends whether the sensitivity of the data you are trying to protect warrants this overhead.
Another, alternative, recommendation from security experts is to store the username in a separate database (and ideally different technology) to the password, and reference between the two using a UUID. E.g. use both MySQL and SQLite. This means that both databases have to be cracked (and is also why, to go down a separate rabbit hole for the sake of an example, you should not store user details and credit card numbers in the same database since one is of no use without the other).
Note that Algorithms like SHA-512 and Blowfish can return the salt as part of their hash. Be careful with these as if you store the complete hash you give away the algorithm, which means there's two less thing for the hackers to figure out (the salt also gives away the algorithm).
Make sure you enforce strong passwords and usernames, so dictionary attacks will fail; I know of dictionaries for all 6-alphanumeric combinations of username/ password entries for MD5 and I suspect that there are more than this available for all sorts of algorithms. With the explosion of low-cost cloud and CPGPU computing, the size and complexity of available dictionaries is going to explode.
Ultimately, the most secure way is never to programatically generate a salt but require a user to enter it along with their username and password over a SSL link (so can't be snooped), but never store it. This is the approach taken by credit card companies; i.e. the 3-digit CSV security key on your credit card which you have to enter each and every time you buy online, since it should never be stored in any database. If you really want to generate the salt, send it to them separately (e.g. via SMS message or Email) and still make them enter it manually each time. With this approach, although more secure, you need to contrast the complexity against whether users will just stop using the site as you've made it too difficult for them to be bothered with it.
All of the above still relies on the fact that you also have protection in place against session hijacking, cross-site scripting, etc., etc. The world's strongest password algorithm is irrelevant if all I need to do is to calculate a valid PHPSESSID for a logged-in user and hijack it!
I am not a security expert, but have read up on this as much as I reasonably can do. The fact that there are so many books on the subject indicates how big the answer to your question really is.
A couple of really great books you might like to try which I've found invaluable are;
Web Application Vulnerabilities Detect, Exploit, Prevent - ISBN-13: 978-1-59749-209-6
Preventing Web Attacks with Apache - ISBN-13: 978-0-321-32128-2
No, time() is not a good salt
It's best not to reinvent the wheel when it comes to authentication, but to answer your question, no. The problem with time():
It's predictable and it correlates to potentially discoverable things. These issues make it easier to cross-match different hashed results.
There aren't very many possible values. Since the high-order bits don't change, it's an even narrower salt than it first appears.
Using it repeats previous mistakes. If this app were the first one to use time() as a salt, at least it would require a new attack.
Yes.
It seems that a unix timestamp, stored in the user database as a "Member since" field going to be decent salt.
However, salt question is most negligible one.
There are much more important things you have to pay attention to:
Most likely not a password nor salt or hashing algorithm going to be weakest part of your site. Some lame file injection or XSS or CSRF surely is. So, don't make a too big deal of it.
Speaking of a true random string of 32 char long in the typical web-application is like speaking about 32-inch armored door in the wooden barn.
Speaking of passwords, most ever important thing is password complexity. With weak password no salt nor hashing algorithm, even super-ingenious-incredible-hard one, could help. It's a pain to ask users to use complex password, but without it everything else becomes a piece of crap.
So, your first concern should be password complexity. 12-16 characters of different case, including numbers and punctuation is a requirement.
As for the salt, I see no benefit in using time, as you have to store it along with other user data. Better use a email - it's random enough and you have it already anyway. Don't forget to rehash a password if user changes their email. it seems that unix timstamp going to be a decent salt, no need to use email or anything else.
Update
As I can see, many people still unable to get the point.
Like that guy from the comments, saying
Many users use weak passwords (we should educate them, or at least keep trying), but that is no excuse; they still deserve good security
They deserve, no doubt. But with weak password the mission. is. impossible.
If your password is weak, then no salt will protect it.
While salt is not that important to spend a 10-kilobyte text on the topic.
Salt is use to prevent rainbow attacks by breaking the match between the password and precomputed hash. So the main task for a salt is to be different for each user/password record. Quality of randomization of the salt doesn't matter much as long as the salt is different for different users.
the date when a member joins a forum/website is generally openly access able , which would be same as time() hence making your salt useless.
No! Never use the current time as the salt. You can use something like 'SecureRandom' in java to generate a random salt that is secure. Always use an unpredictable random number as the salt. Using time as the salt will help you to remove collisions only upto a certain extent(because two users can sypply the same passwords at the same time), but still make the passwords recoverable.
The user name should be sufficient enough and perhaps the registration time stamp, but you should store it somewhere in the database. Anyway every value you use to salt your password hash, should be stored some way, so you can recalculate the hash.
Is salting with user name + a time stamp secure enough? It should be. For cracking SHA512 Hashes normally Rainbow Tables are used. A user name + a time stamp should be a salt which is uniquq enough, so there is no way there is some Rainbow Table on the net which contains precalculated hashes with passwords, which are salted this way.
I have used unsalted md5/sha1 for long time, but as this method isn't really secure (and is getting even less secure as time goes by) I decided to switch to a salted sha512. Furthermore I want to slow the generation of the hash down by using many iterations (e.g. 100).
My question is whether I should append the salt on every iteration or only once at the beginning. Here are the two possible codes:
Append every time:
// some nice big salt
$salt = hash($algorithm, $salt);
// apply $algorithm $runs times for slowdown
while ($runs--) {
$string = hash($algorithm, $string . $salt, $raw);
}
return $string;
Append once:
// add some nice big salt
$string .= hash($algorithm, $salt);
// apply $algorithm $runs times for slowdown
while ($runs--) {
$string = hash($algorithm, $string, $raw);
}
return $string;
I first wanted to use the second version (append once) but then found some scripts appending the salt every time.
So, I wonder whether adding it every time adds some strength to the hash. For example, would it be possible that an attacker found some clever way to create a 100timesSha512 function which were way faster than simply executing sha512 100 times?
In short: Yes. Go with the first example... The hash function can lose entropy if feed back to itself without adding the original data (I can't seem to find a reference now, I'll keep looking).
And for the record, I am in support of hashing multiple times.
A hash that takes 500 ms to generate is not too slow for your server (considering that generating hashes are typically not done the vast majority of requests). However a hash that takes that long will significantly increase the time it will take to generate a rainbow table...
Yes, it does expose a DOS vulnerability, but it also prevents brute force attacks (or at least makes them prohibitively slow). There is absolutely a tradeoff, but to some the benefits exceed the risks...
A reference (more like an overview) to the entire process: Key Strengthening
As for the degenerating collisions, the only source I could find so far is this discussion...
And some more discussion on the topic:
HEKS Proposal
SecurityFocus blog on hashing
A paper on Oracle's Password Hashing Algorithms
And a few more links:
PBKDF2 on WikiPedia
PBKDF2 Standard
A email thread that's applicable
Just Hashing Is Far From Enough Blog Post
There are tons of results. If you want more, Google hash stretching... There's tons of good information out there...
In addition to re-hashing it multiple times, I would use a different salt for each password/user. Though I think 5000 iterations is a bit too much, try a lower number. There's a trade-off here; you'll have to tweak it according to your needs and hardware.
With different salts for each password, an attacker would be forced to bruteforce each password individually instead of constructing a rainbow table, which increases the workload considerably.
As always, here's a recommended read for this: Just hashing is far from enough
EDIT: Iterative hashing is a perfectly valid tactic. There are trade-offs, but everything has them. If you are worried about computation time, why not just store the plaintext password?
Please please please do not roll your own crypto. This is what libraries like OpenSSL are for. Here's few good examples of how you would use it to make salted hashes.
Salted Hashes in OpenSSL
The reason for iterative hashing is to make process as slow as possible. So you can do even better: use different salts for each iteration. It can be done by encrypting you original data again and again on each iteration with fixed key and XORing with salt value.
I prefer to go with a double sha1 with two different salts and prevent DoS delaying the answer incrementally (with a simple usleep) for every invalid password check.
I am going to generate a random password for my users. Probably I will use salt and sha1 method. But I found that there are other version of sha1, like sha256, sha512 etc.
What is the differences between the sha versions? Which one better, more secure, and faster (performances)? Which one should I use??
EDIT:
I am php user, thanks :)
Password generation is not as straightforward as you may think. For instance, if you're generating a password for a site which can be accessed from a mobile phone (or any device with only a numerical keyboard) you should ensure that no two consecutive characters in your password are on the same key since that would be a huge UI flaw.
An example: consider dfe4Pl7 as a password. In order to type it in, a used should press 3 once, than wait, then press 3 three times, then wait again and press '3' two more times. This sucks.
In more general terms, password should be generated so that misinterpretation is avoided as much as possible. For example, I'd personally avoid including 1's and l's, 0's and O's, etc.
The bottomline is: hashing algorithms will be of a very little help here. What you need is a good random-number generator and a UI-wise solid generation algorithm.
You are confusing two issues here. Random password generation, which is basically picking random symbols of a certain (minimum) length, and password storage, which in practical terms involve storing a hash of the password with a salt so that the plaintext password can't be discover just by reading the database.
Generation
To pick random symbols, you have an array of all the symbols, get a random number and subscript into the array using that number as index to return a symbol. This is what Kane Wallmann suggested earlier. However, for security related application such as password generation, one need a cryptographically strong pseudo-random number generation, which rand() is not.
Storage
As noted earlier, password shouldn't be stored in plaintext in the database. Otherwise, anyone with access to it can just read it and know what the password of any and all particular user password are. What happen is a hash of the password is store instead. When a user attempt to login, their password is hash and compare to the value in the database to see if it's the same. The hashing function is what's call a one-way function. You can hash the password to get a hashed value, but you can't get the password from the hash value without trying all possible combination to see if it matches. (At least, that's the idea anyway.) It's more complicated than that of course, since hash value output is fixed length, whereas the possible input while in practical terms isn't infinite is definitely more than the possible number of output.
Now, where salt comes in is because simple hashing of the password alone isn't secure either. For one, such a method would give the same hashed value for any two users with the same password. Compromise of one account would result in the compromise of the other. Secondly, what an attacker can do is to build what is called a rainbow table ahead of time. While this take time, it only have to be done once for any storage algorithm, and he or she don't have to do it themselves. The work can be spilt over many computers, and there's in fact websites on the internet where you can download such rainbow tables for weak password hashing system such as LM and NTLM. After that, the attacker can just look up any particular hash value against the table and determine the plaintext password. So to protect against that, a random (per user) salt value is added to the password before it is hashed. This makes the input different even for the same password, so prevent the first problem. It also mitigate against the second problem if the salt & password combined is long enough as the length of the input is such that it would become computationally infeasible to brute force it.
As to the question of which particular SHA, or for that matter, other hashing algorithms to use. SHA is a US NIST standard, and are acknowledged to be pretty good. There's been a little theoretical breakthrough into SHA-1, but in practice it's still secure enough for most purpose. The SHA-2 algorithms are better than SHA-1, with no known breakthrough. Which variant to choose are down to various things including size. They produce different length output, and different amount to calculate because of the size difference. PHP have native implementation of SHA-1, SHA-256, 384, and 512, among a number of others hashing algorithms.
After all that, in practice, which of the SHA algorithms you choose probably doesn't matter as the weak point in your system are likely elsewhere. Users writing down their passwords. Users using the same password across different systems. Programming flaw that allow things like XSS and SQL injection. Etc. etc.
Encryption algorithm security doesn't mean anything if you are simply using them to make random letters and numbers for a password. You are better off making a random password function, it would be MUCH more efficient.... Why are you salting anyway?
Here is a SIMPLE password generator written in PHP.
function RandomPassword( $length )
{
$characters = "abcdefghjklmnpqrstuvwxyz23456789";
$result = "";
for( $i=0; $i < $length; $i++ )
{
$result .= $characters[ rand( 0, strlen( $characters )-1 ) ];
}
return $result;
}
NOTE: i,1,0 and o are intentionally missing as they are easily mistaken as each other.
here's the wiki you can read about sha
there it talks about sha-2 family being algorithmically similar, however sha-1 is more popular.