For my website's password hashing I wrote the following function:
public function hash($user) {
$user_key = hash_hmac('sha512', $user['id'].$user['email'], $this->site_key);
$password = hash_hmac('sha512', $user['password'], $user_key);
}
I generate user unique keys to use for the final password hashing. Because this key is hashed with sha512 it should give enough security based on what I read on wikipedia:
The cryptographic strength of the HMAC depends upon the cryptographic strength of the underlying hash function, the size of its hash output length in bits and on the size and quality of the cryptographic key.
I have not seen this way if hashing passwords before and was wondering if it is good enough?
Extra: I have not used a salt because I think hmac appends the provided key to the data (like a salt), is this right?
OK, first and foremost. Do not write up your own function to do password hashing. I'm not doubting your skills, but to be safe do not do your own hashing system. And an HMAC your key is OK, but I'd still not use it.
Finally I'd suggest that you do this for your users passwords.
<?PHP
$password=$user['password'];
$username=$user['username'];
$salt='usesomesillystringforsalt';
$hashed_password=crypt($password.$username,'$2a$04$usesomesillstringforsalt$');
?>
This algorithm uses Bcrypt which is based upon Blowfish it is a very robust algorithm and is what Gawker media went to after they were hacked due to the robustness and usefulness for password hashing. crypt PHP Manual
Next up, remember to change the part that says usesomesillystringforsalt to something else. It needs to be 22 digits of base64 salt A-Z,a-z,0-9,/ and "."
Go to that link to find out more about the algorithm itself. I suggest that you just use this implementation as it is much much stronger than the one that you were suggesting.
If you want to go a step forward, I'd suggest that you use a unique salt for every user. If you want to do that, I can write up an example function which will show you how to do that.
As stated, if you have any more questions feel free to ask.
Related
I know that there are alots of questions about this subject but i really need to ask this.
Today I've been working on encrypting passwords with md5.
So what I've done is.
I got 4 salts. (they changes depending on user values)
from email id and substr then md5 them
from email and id substr other positions
a long string, substr it and then md5 it
another long string, substr it and then md5 it
Then i md5 salt1 and 3 and the password with salt 2 and salt4
After this I have to change the password automatically whenever a user changes his email or his id getting changed.
What do you guys think about this?
Nothing.
MD5 is broken and bad.
Using the mailaddress as salt is a good idea. But using md5 is not. Use instead bcrypt, scrypt or pbkdf2.
Don't invent your own ecryption, unless you really know what you are doing, and trust me, you don't
First, let us define a few terms.
Encryption is when you encode a message so that it cannot be read. Encryption involves a plaintext, a cipher and a key. It is like putting a book (the plaintext) in a locked room (cipher), which can only be opened using a known tool (a key). There are many kinds of encryption, but that is a simple description. Encryption is two-way, meaning that you can encode and decode the message.
Cryptographic hash is when you take any kind of data and generate a fixed size value for it (usually called a hash or a digest). Cryptographic hashes are one-way, which means that you cannot reverse the process.
A salt is a unique string, or a collection of bits, similar to a nonce (a unique number that is only used once). Salts are only used to make it infeasible for a cracker to process a list of hashes. They are not supposed to be used as a secret (i.e. like a cryptographic key). The only reason people usually talk about randomness when it comes to salts is because they want to generate a unique salt (if the randomness is not great enough they may get colliding salts, for instance).
Okay, now to how you should hash a password.
A relatively safe way of hashing a password is to simply tack on a unique hash onto a password, and then save the salt with the password:
$pass = 'this is my password';
$salt = uniqid('', true);
$hash = sha1($pass . $salt);
// INSERT INTO users ('hash', 'salt') VALUES ('$hash', '$salt') WHERE ...
That is an okay way of doing it if your website does not retrieve any sensitive data from its users.
If you deal with sensitive data, or if you just want to make sure that you are doing everything you can to keep stuff safe, then there is a PHP function that does the hashing for you. It is called crypt() (read the documentation to learn how it works). Here is an example of how to hash a password using the function:
$pass = 'this is my password';
$salt = 'unique string';
$hash = crypt($password, '$2y$07$'.$salt.'$');
echo $hash;
That will securely hash a password.
The thing to realize is that the crypt() function is much more secure than anything you can come up with (unless you are a specialist in the area).
In newer versions of PHP (5.5.0+) there is a password hashing API that makes it even simpler to hash a password.
There are also various hashing libraries out there. PHPass is a popular one.
It is bad, because it uses MD5.
MD5 is a very fast operation. It can be executed billion of times per second on graphic cards hardware. It is considered bad practice to use it for any password related things.
Use bcrypt. Use a random salt. Use the upcoming PHP API for hashing, verifying and rehashing passwords. This include file implements it for versions starting with PHP 5.3.7: https://github.com/ircmaxell/password_compat
Well, "MD5 is broken and bad" is a little exagerated. Even if it can be brute-forced with a lot of CPU, it is not "broken" and is still a very useful algorithm for a lot of things involving hashing.
So "MD5 should not be used for password encryption" sounds much better to me.
When using PHP, an easy and safe option is to rely on the password_hash() (which natively generates a random salt) and password_verify() functions.
The advantage is that the encryption algorithm will transparently be updated with each new PHP version (at the moment PASSWORD_DEFAULT is set to bcrypt, but should bcrypt be "broken" it can be set to a newer algorithm), which makes any code using those functions quite resilient.
I personally do not recommend involving of the user id and his email into the hashing of his password.
You can deal with the password by:
Dynamic salt per user based on random string generated on user registration
Prepend one part of the salt and append the other around the password
Double md5: md5(md5($password))
Etc.
a simple way would be to generate a random salt for each user and hash your password like this
public function encodePassword( $raw, $salt ) {
return hash('sha256', $salt.$raw);
}
For high security hash, you can check this link which explain how to implement PBKDF2:
http://crackstation.net/hashing-security.htm#phpsourcecode
I'm the developer of a new website built in PHP and I'm wondering what exactly is the best
thing to use for hashing. I've looked at md5 and sha1 but is there anything more secure.
I'm sorry if this is a nooby question but I'm new to PHP Security and I'm trying to make my
site as secure as possible. Also what is a salt?
Thanks,
Waseem
First off md5 and sha1 have been proven to be vunrable to collision attacks and can be rainbow
tabled easily (When they see if you hash is the same in their database of common passwords).
There are currently two things that are secure enough for passwords, that you can use.
The first being sha512. sha512 is a sub-version of SHA2. SHA2 has not yet been proven to be
vunrable to collision attacks and sha512 will generate a 512 bit hash. Here is an example of
how to use sha512:
<?php
hash('sha512',$password);
The other option is called bcrypt. bcrypt is famous for its secure hashes. Its
probably the most secure one out there and most customizable one too.
Before you want to start using bcrypt you need to check if your sever has it enabled, Enter
this code:
<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
echo "CRYPT_BLOWFISH is enabled!";
}else {
echo "CRYPT_BLOWFISH is not available";
}
If it returns that it is enabled then the next step is easy, All you need to do to bcrypt a
password is (Note for more customizability you need to see this How do you use bcrypt for hashing passwords in PHP?):
crypt($password, $salt);
Now to answer your second question. A salt is usally a random string that you add at the end of
all you passwords when you hash them. Using a salt means if some one gets your database
they can not check the hashes for common passwords. Checking the database is called using a rainbow table. You should always use a salt when hashing!!
Here are my proofs for the SHA1 and MD5 collision attack vulnerabilities:
http://www.schneier.com/blog/archives/2012/10/when_will_we_se.html, http://eprint.iacr.org/2010/413.pdf, http://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdf, http://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdf and Understanding sha-1 collision weakness
The whole purpose of the salt is to slow down an attacker from comparing a list of pre-generated hashes against the target hash.
Instead of needing to pre-compute one "hashed" value for each plaintext password, an attacker needs to precompute 16384 "hashed" values for each plaintext password (2^7 * 2^7).
That kinda pales today but was pretty big when the crypt function was first developed - the computational power to pre-compute that many passwords times the number of plaintext password you suspect (dictionary) was pretty high.
Not so much today which is why we have things like shadow passwords, other core password functions besides crypt and every sysad wanting you to pick a password that would not show up in a dictionary.
If the hashes you want to generate are for passwords this is a well accepted method of implementing it.
http://www.openwall.com/phpass/
If you're planning to do this for passwords, then do not use MD5 or SHA1. They are known to be weak and insecure, even with salt.
If you're using them for other purposes (eg providing a hash of a file to confirm its authenticity, or a random hash database column to provide a pseudo-random sort order) then they are fine (up to a point), but not for passwords or anything else that you would consider needing to be kept secure.
The current best-practice algorithm for password hasing is BCrypt, with suitable salting.
And the best way to implement BCrypt password hashing in PHP is to use PHP's new password API. This API will be featured as a set of built-in functions in the next version of PHP, v5.5, due for release in the next few months. The good news is that they have also released a backward-compatibility version for users of current versions of PHP (5.3 and 5.4), so even though PHP 5.5 isn't released yet, you can start using the new API immediately.
You can download the compatibility library from here: https://github.com/ircmaxell/password_compat
Also: You asked what "salt" is. Since I've mentioned it a couple of times in this answer, I should address that part of the question too.
Salt is basically an additional string added to the password when hashing it, in order to make it harder to crack.
For example, an attacker may know in advance what the hashed value is for a given password string, or even a whole lot of given password strings. If he can get hold of your hashed data and you haven't used a salt, then he can just compare your hashes against his list of known passwords, and if any of your users are using an easy to guess password, they'll be cracked in seconds, regardless of what hashing method was used.
However, if you've added a secret extra string to the password when you hash it, then the hashed value won't match the standard hash for the original password, thus making it harder for the attacker to find the value.
The good news is that if you're using the API I mentioned above, then you don't need to worry too much about the details of this, as the API handles the salting for you.
Hope that helps.
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 using this code to hash passwords:
hash_hmac('sha512', $password . $salt, $hmac_key);
Is 4096 bits enough for a key?
Thank you!
For password hashing? Sure. Just long enough salt will be enough.
You need to realise, what is the purpose of your using hash here. You're hashing passwords, so that if anyone gets hold of these hashes, they cannot infer original passwords from them. We use salts, so that brute force and rainbow table based attacks are less effective, and we make salts unique for each password, so that two users, using same passwords have different hashes. HMAC does not add anything to security here, except acting as kind of salt.
HMAC is relevant, when you use hashing function as a digital signature of message/file (the way php.net uses it one their downloads page for example). You use HMAC key, so that only people that know this key can verify authenticity of hashed content (as contrasted to php.net downloads, where everyone can check md5 of downloaded file) and to make it more difficult to spoof the message that produces same hash (you need to know the key, to know what hash to target)
I realize that this topic have been brought up sometimes, but I find myself not entirely sure on the topic just yet.
What I am wondering about how do you salt a hash and work with the salted hash? If the password is encrypted with a random generated salt, how can the we verify it when the user tries to authenticate? Do we need to store the generated hash in our database as well?
Is there any specific way the salt preferably should be generated? Which encryption method is favored to be used? From what I hear sha256 is quite alright.
Would it be an idea to have the hash "re-salted" when the user authenticates? And lastly is it any major security boost to rehash it a bunch of times?
Thank you!
The answer is to not do it yourself. The one-liner that will do everything you need in PHP is to use bcrypt.
Read this, it's easy to understand and explains everything you asked: http://codahale.com/how-to-safely-store-a-password/
bcrypt takes into account the hashing by itself, and can be configured to be as "complex" as necessary to maintain the integrity of your users' passwords in the event of being hacked.
Oh, and we don't "encrypt" passwords, we hash them.
You need to store both the hash and the salt that has been used to calculate the hash.
If you then want to check if an input is equivalent to the original input value, you can re-calculate the hash with the same salt and compare the stored hash with the new calculated one. If they are equal both input values are identical (up to some particular probability).
The choice of hashing algorithm is also important. Because there are fast hashing algorithms and rather slow hashing algorithms. And as you want to make is hard to find a collision (at least in brute-force), use a slower hashing algorithm.
What I am wondering about how do you
salt a hash and work with the salted
hash? If the password is encrypted
with a random generated salt, how can
the we verify it when the user tries
to authenticate? Do we need to store
the generated hash in our database as
well?
Yes. First you generate a salt, then generate a hash from the password plus the salt and save both hash and salt together.
Is there any specific way the salt
preferably should be generated?
I doubt that there's consensus on what's preferable. I use /dev/random. e.g.
$salt = '$2a$12$'
. strtr(substr(base64_encode(shell_exec(
'dd if=/dev/random bs=16 count=1 2>/dev/null'
)), 0, 22), '+', '.')
. '$';
$hash = crypt($input, $salt);
Which encryption method is favored to
be used? From what I hear sha256 is
quite alright.
See Computer Guru's answer, i.e. use bcrypt as in the example above. See the PHP manual page on crypt(). If bcrypt isn't on your system, one way to get it is the Suhosin patch.
Would it be an idea to have the hash
"re-salted" when the user
authenticates?
The salt just makes dictionary attacks slower. If you have a decent random salt to start with I wouldn't think changing it frequently would help. You'd probably be better off investing your effort in making users choose good passwords, changing them often enough and keeping your Blowfish cost parameter at a sensible value.
And lastly is it any major security
boost to rehash it a bunch of times?
That question belongs in the world of cryptographic design. I recommend you leave that to the experts. In other words: forget it—just use best common practices.
What generally you do is something like:
salted = HASH(password . key); // DON'T DO IT LIKE THIS
Where key is "the salt" - the secret key stored in configuration files. So in order to crack the password you would need both the secret key and the DB so it is good to store them
in separate places.
Because the schema I had shown is not strong enough, it is better to use HMAC for this purpose rather then hand written salting. Such an operation is as simple as hash and PHP supports this.
salted = hash_hmac('sha1',password,key); // <-- this is ok
See this: http://php.net/manual/en/function.sha1.php
Three simple rules. Okay, five:
Most important thing, if you want to consider your password storage being safe: allow strong passwords only e.g. at least 8 chars with some different case letters and numbers and even punctuation marks
Allow users to use strong passwords only. Make a routine to check length and character range and refuse weak passwords. Even get yourself John the ripper database and check against it.
Torture users wickedly, beat them up, until they choose good long and random enough passwords. Passwords! Not salt, of which everyone is delighted to talk for hours, but password itself should be random enough!
Salt your passwords and store that salt along with user info. you can use user email and username as a perfect salt, no need to invent something extraordinary random.
Certain algorithm is not that important, you can use MD5 as well. In real world there are very few people who would bother themselves with cracking user database of your famous Fishing And Grocery Fans Society site forums.