I need to store a password in a database, and I used to store an sha1 hash of a salted password alongside a random salt, which was looped, like so:
$salt = sha1(microtime().mt_rand());
for ($i=0; $i < 4000; $i++) {
$password = sha1($password.$salt);
}
(In my example, $password and $salt were stored inside the db).
I recently discovered the hash_hmac() function, which apparently is a much more secure function than a simple SHA1 hash. I plan on using it with the same pattern (the salt being the secret key), but I was wondering if it was worthwile to loop it like in my previous example. If anyone could give me some insight, that'd be much appreciated.
Yes.
What you're doing here is known as key stretching and it multiplies the time an attacker has to take to check each candidate password against a hash. In your example, it increases the time by 4000x. The specific threat you are protecting against here is when an attacker gets hold of your hashes (such as what happened with LinkedIn, Last.fm and eHarmony recently) and can devote as much CPU power as he can afford to cracking them.
Rather than rolling your own, if this is anything other than a research project, you should use a well-known and publicly tested function like bcrypt(), PBKDF2() or scrypt().
The number in that loop should be much higher than 4000 and since your attacker will be using a C loop rather than a PHP loop, you won't be able to do as many in a reasonable time as he will. Even in a PHP loop, I can do 500,000 in 0.3 seconds. The above hashing algorithms solve this problem since they will be implemented in C. (Not all of them may be available in PHP.) It seems bcrypt is in 5.3 but it's called CRYPT_BLOWFISH. Details on how to use it are on the crypt() page.
hash_hmac() is not a more secure hashing algorithm but rather is used for a different purpose. See the end of Thomas' answer here. Algorithms like MD5 and the SHA family are general purpose hashing algorithms that are normally used as part of a more specific algorithm for a particular purpose. For instance, some of the above password hashing algorithms use general purpose hashing algorithms many times. has_hmac() asks you which general purpose hashing algorithm you would like to use.
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.
Am working on a project & am keen to keep password-storage secure from the start. In the idea phase, but this is roughly what I intend to use.
class Crypto {
public function hash1($string, $salt) {
return hash('sha512', $string . $salt);
}
public function hash2($string, $salt) {
return hash('sha512', $salt . $string);
}
public function compareToHash($string, $salt, $hash1, $hash2) {
return($this->hash1($string, $salt) === $hash1 && $this->hash2($string, $salt) === $hash2);
}
}
As you can see I am trying to avoid collisions. Is this an effective way, it seems awfully simple and I wonder if I am missing something.
Thanks.
Since you plan on password protecting possibly a website, let me explain that you will need to make sure to send a password from the client already encoded or else any sniffer will find the real password, and you know how people usually use password, right? The same on many, many accounts.
I would suggest taking a look at a post I stubled upon some time ago, and preserved a link for it, for it explains all the problems with hashing and password protection: http://www.codinghorror.com/blog/2007/09/rainbow-hash-cracking.html
Shortly - use the strongest (and sha1 is not strong any more) password encoder as it is possible. Not the fastest one. Let the hacker loose valuable time trying to break in. So much, that breaking in will become unattractive.
Hope it will help, and good luck.
That is pretty basic. I'd check out the Password Storage Cheat Sheet from OWASP. There are also lots of password hashing libraries already created and vetted.
I'd take a look at the Portable PHP Hashing Framework by OpenWall. It creates very secure hashes and performs an appropriate number of iterations as well. It's pretty widely used too.
If you are hashing with SHA512, there isn't anything special you need to do at the time for collision avoidance, I remember reading recently that finding collisions is still not feasible for some time still.
The two primary things I would focus on are secure salts (20+ bytes) and to iterate the hash at least 64,000 times to increase the attack time.
The first rule of password security: If you're not sure if something is secure, then the odds are it isn't.
Since you're just starting out writing your password routines, my advice is to stop now.
PHP5.5 (due out Feb/Mar 2013) will come with a set of new functions designed specifically for dealing with passwords with the best practice security in mind. When 5.5 is released, these functions will become the only recommended method of handling passwords in PHP.
The good news is that you don't have to wait or upgrade to 5.5 in order to use these functions -- they've been back-ported to run in 5.3 and 5.4, so you can use them now. Download the library from here: https://github.com/ircmaxell/password_compat
Reference article: http://www.h-online.com/open/news/item/PHP-5-5-should-reduce-password-sloppiness-1707835.html
If you want to make your password storage secure from the start, you should not use sha512 or any other fast hash algorithm, instead use a key derivation function like BCrypt.
The problem with fast algorithms is, that you can calculate 80 Mega sha512-hashes per second with common hardware (in 2012). That makes it possible to brute-force a whole english dictionary with about 500000 words, in a few milliseconds! Other algorithms are even faster.
BCrypt was especially designed to hash passwords, and is therefore slow (needs some computing time). With a cost factor you can adapt the needed time to future (and therefore faster) hardware.
Using BCrypt can be as easy, as using the sha512 hash. It's recommended to use a well established library like phpass, and if you want to understand how it can be implemented, you can read this article, where i tried to explain the most important points.
Your scheme with two separate hashes will not increase security, because collisions with sha512 are never the problem. In the worst case it even weakens security, because you have to store both hashes, so an attacker has two related informations about the hashed password.
I want to use SHA512 to store passwords. To do that, which of openssl_digest, hash and hash_hmac should I use and why?
What is the difference between SALT & HMAC?
I just read that HMAC is built on top of hash function.
So is SHA512+SALT+HMAC really necessary or SHA512+SALT or SHA512+HMAC?
So, first off, let's clear one thing up. openssl_digest() === hash(). It's just another function by a different name that does the exact same thing. It computes a cryptographic hash of the input.
So, now we have the question: When storing passwords, which is better: hash or hash_hmac?
Short Answer:
Neither
Long Answer:
As it turns out, The Rainbow Table Is Dead. Just using hash($password . $salt) or even hash_hmac($password, $salt) is not good enough for password storage. Period. If you're doing so, stop right now.
The reason is simple: computation time on a computer (or GPU) is incredibly cheap. It's so cheap, that to brute force a list of passwords is cheap enough that you need to worry about it. Remember, hash functions are designed to be fast. Not expensive...
But, as it also turns out, there is a way to make those fast hash functions more expensive. In fact, it's pretty simple: iterate.
Now, I know what you're thinking. You're going to just loop over the hash:
function hash_password($password, $salt) {
$hash = hash("sha512", $password . $salt);
for ($i = 0; $i < 1000; $i++) {
$hash = hash("sha512", $hash);
}
}
Surely that's good enough, right? Nope. As explained in Fundamental Difference Between Hashing and Encryption, that's not a good idea. So why not just feed back the password and salt in again?
function hash_password($password, $salt) {
$hash = hash("md5", $salt . $password);
for ($i = 0; $i < 1000; $i++) {
$hash = hash("md5", $hash . $password);
}
}
In fact, this is exactly what PHPASS uses (slightly tweaked, but this is the base algorithm)...
So now 1 call to hash_password executes 1000 hash cycles.
But can we improve on that?
Well, as it turns out, we can. The next logical thing to do would be to see if we can get more hash cycles for the same amount of time. And this is where hash_hmac() comes in. As it turns out, HMAC uses 2 hash cycles each time it's called. And because it's all C, it only takes about 1.5 times the amount of time that hash() takes to do a single round.
So that means if we replace hash with hash_hmac, we can instantly see a 33% increase in the amount of work being done in a specified time. So now we're here:
function hash_password($password, $salt) {
$hash = hash_hmac("md5", $salt, $password);
for ($i = 0; $i < 1000; $i++) {
$hash = hash_hmac("md5", $hash, $password);
}
}
And this is actually the basic inner-loop of PBKDF2.
But can we get better?
Yes, again, we can get better. If we look closely, we can see that -in addition to password and salt- all of the above algorithms use a very small amount of memory. In the case of sha512, they'll use on the order of 128 to 256 bytes (buffers and state) to hash the password. Since the memory use is so small, it's trivial to run a lot of them at once side-by-side in a GPU. If we could only increase the memory usage...
Well, as it turns out, we can simply use bcrypt, which is an adaptive hashing algorithm. It has an advantage that it uses more memory than the above algorithms (on the order of 4 to 5kb). So it's more resistent to parallelizing. And it's resistent to brute forcing since it's computationally expensive.
Luckily, it's available for PHP:
crypt($password, '$2y$07$usesomesillystringforsalt$')
Note that crypt() uses many algorithms, but the $2y$ and $2a$ algorithms are bcrypt.
But can we improve on this?
Kind-of. There is a relatively new algorithm called scrypt. It's better than bcrypt, because it's just as computationally expensive, but uses a LOT more memory (on the order of 20mb to 40mb to hash a single password). Therefore, it's even more resistent to parallelization...
Unfortunately, scrypt is not available in PHP yet (I'm working on changing that). Until then, use bcrypt...
Sidenote
After the recent lessons from LinkedIn, LastFM, Hotmail, Gawker, etc, the proof is apparent that a lot of people are doing it wrong. Don't do it wrong, use a library with a vetted algorithm. Use CRYPT_BLOWFISH (bcrypt), use PHPASS, use PasswordLib. But don't invent your own just because you don't want to pull a dependency... That's just negligence.
More reading:
Properly Salting Passwords - The Case Against Pepper
GPU Accelerated PBKDF2
Many Hash Iterations, Append Salt Every Time?
MD5 Decoding, How Do They Do It
HMAC is a specific way to use a hash algorithm (like SHA512). It's used to sign a message and you can then verify that the message is from a specific signer and has not been altered. So this isn't what you want.
A salt is used to add a bit of "randomness" to a text that should be encrypted or hashed. The point is that even if you encrypt the same text several times you'd get different results. This makes it harder to do some attacks. This is what you want: SHA512(salt+password).
For storing passwords, the most secure way I could imagine would be:
(disclaimer: I'm not very experienced with cryptography and there might be a better solution)
Client (JavaScript code?) would generate a salt value.
The client then combines salt and password, and run the result through your hashing algorithm.
The client then transmits both salt and hash value to the server which stores it (preferably in different locations).
To verify a password, you'd then do:
Pass the salt to the client.
Client combines salt and entered password, runs it through your hashing algorithm.
Client sends the hash value to the server.
Server compares the hash value with the stored hash value. If they match, it was the same password.
Of course you could transmit the password in plaintext and do the whole salting and hashing on the server, but this would weaken your solution dramatically. You should never transmit the password in plaintext.
But the "pass the salt to the client" part might be a problem. One way that I could imagine to solve this would be to somehow derive the salt from the username (easiest way: simply do lowercase(username) + password), but the problem with that would be that the salt would be predictable and thus weakening your solution a little bit. Yet, it's still way better than transmitting the "raw" hash and you wouldn't even need to store the salt as you could derive it from the username every time. Should your password DB get stolen it would still resist a rainbow table attack with this "salting with username" approach.
The problem is that a man-in-the-middle attack is still possible. If an attacker would intercept username and hash it has all the relevant infos and it wouldn't be any different than transmitting the plaintext password. So you might want to secure the connection with SSL (HTTPS).
According to IT Security experts:
Use Bcrypt Source: https://security.stackexchange.com/a/10905/7599.
I would give answer according to SO point of view.
openssl_digest vs hash vs hash_hmac
openssl_digest - Computes a digest.
hash Generate a hash value (message digest)
hash_hmac — Generate a keyed hash value using the HMAC method
And In cryptography, a hash-based message authentication code (HMAC) is a specific construction for calculating a message authentication code (MAC) involving a cryptographic hash function in combination with a secret key.
As said by ircmaxell, hash or hash_hmac are not better for storing passwords with SHA-512. I would rather say, you can use openssl_digest for storing passwords.
See SHA-512 library for PHP
SALT vs HMAC
A hash, in this context, is a one-way function - i.e. a function that makes it very easy to find the result from the argument (the password) but difficult (or impossible) to find any argument that generates a given result.
A salt is some auxiliary data that augments the argument to a hash function. This is useful as it prevents accidental discovery of passwords through observation that two hashed passwords have identical values. With a salt, the stored/transmitted value will only be identical if both the salt and the password match.
An HMAC refers to the application of a hash (and optional salt) to a "message authentication code" - which, depending upon context might be a password... or, at least, there's nothing stopping you passing a password into the HMAC as if it were the message authentication code.
HMAC is meant to be used in cases where you have a random and secret
key. For these cases, HMAC is usually better than other ways of
incorporating the key into the hash function. (For example, using HMAC
takes care of things like extension attacks, etc.)
Salt is usually a random value that is not secret. That is to say, when
you use the term salt you usually refer to situations where there is a
random value that may very well be known to the attacker. The security
of the system should therefore not depend on the salt being kept
secret. In these situations HMAC is often not a very good choice.
HMAC and Salt comparison is not logical. Personally I'd use a salt and a hash function... and I wouldn't be paranoid about the strength of the hash function as its unlikely to be the weak link in any practical system....
See http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html
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 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.