Related
In light of how many major websites have been hacked and their databases of password decrypted what is the best way to secure authentication?
Basically I am interested in a way to secure access to a part of a site to members in a way that if hacked would under no circumstances let hackers get a hold of the user's passwords.
Nothing is invulnerable but at least make it very difficult to crack.
http://codahale.com/how-to-safely-store-a-password/
Use bcrypt
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Use bcrypt.
Why Not {MD5, SHA1, SHA256, SHA512, SHA-3, etc}?
These are all general purpose hash functions, designed to calculate a digest
of huge amounts of data in as short a time as possible. This means that they are
fantastic for ensuring the integrity of data and utterly rubbish for storing
passwords.
A modern server can calculate the MD5 hash of about
330MB every second. If your
users have passwords which are lowercase, alphanumeric, and 6 characters long,
you can try every single possible password of that size in around
40 seconds.
And that’s without investing anything.
If you’re willing to spend about 2,000 USD and a week or two picking up
CUDA, you can put together your
own little supercomputer cluster which will let you
try around 700,000,000 passwords a second.
And that rate you’ll be cracking those passwords at the rate of more than one
per second.
Salts Will Not Help You
It’s important to note that salts are useless for preventing dictionary
attacks or brute force attacks. You can use huge salts or many salts or
hand-harvested, shade-grown, organic Himalayan pink salt.
It doesn’t affect how fast an attacker can try a candidate password, given the
hash and the salt from your database.
Salt or no, if you’re using a general-purpose hash function designed for speed
you’re well and truly effed.
bcrypt Solves These Problems
How? Basically, it’s slow as hell. It uses a variant of the Blowfish
encryption algorithm’s keying schedule, and introduces a work factor, which
allows you to determine how expensive the hash function will be. Because of
this, bcrypt can keep up with Moore’s law. As computers get faster you can
increase the work factor and the hash will get slower.
How much slower is bcrypt than, say, MD5? Depends on the work factor. Using
a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on
my laptop. MD5, on the other hand, takes less than a microsecond.
So we’re talking about 5 or so orders of magnitude. Instead of cracking a
password every 40 seconds, I’d be cracking them every 12 years or so. Your
passwords might not need that kind of security and you might need a faster
comparison algorithm, but bcrypt allows you to choose your balance of speed
and security. Use it.
Besides proper password handling (like bcrypt, as already mentioned), you need to do the password hashing on a dedicated device/machine.
This "device" for password hashing is a separate system which contains so called "local parameter", which is an extra input to the hash function (say, 128-bit strong random number). This local parameter must be unreadable by the host system (your app, which does the user authentication).
Using such a dedicated machine for password hashing buys you an extra layer of security if your password database/app gets compromised.
I want to use Bcrypt for the password encryption in my systems. But all the examples are something like this:
$password = $_POST['password'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($password, '$2a$12$'.$salt);
This looks pretty safe to me, but I was wondering, in each example, nobody hashes the password before using Bcrypt.
Due to the unique salt, Rainbow tables shouldn't be able to crack all the passwords at once. But in case the hacker takes one record and creates a rainbow table with the salt of that particular record, he should be able to crack a weak password.
So if someone takes a weak password (let's say 'foo'), it would be safer to hash it first with SHA-512 before using Bcrypt. Am I right? Or is this just looking safer?
Actually the answer has to be no, it doesn't make the hash significant stronger in a cryptographically sense. As you probably know, bcrypt (although the function to use is named crypt) is a hash function itself, not an encryption function.
In bcrypt you pass a cost factor, which defines, how many iterations will be done (normally hundreds of them). That slows down calculation of the hash, what makes brute force attacks impracticable. Using SHA-512 before, will only add one iteration more.
What you said about the salt is correct, but of course if you have to build a rainbow table for each password, you will simply brute force until you have found a match, no need to build the whole rainbow table.
If the attacker has control over database and code, an additional SHA-512 will help nothing at all (only a single iteration more). If he has only the database without code (SQL-Injection), then he will recognize the bcrypt hash. He can now brute force with bcrypt, but because of the SHA-512 there aren't any weak passwords. It's like the SHA-512 hash would be the password to crack, so a dictionary is of no use. This is security by obscurity, but will be effective as long as the code is not known. You can get the same effect easier, by adding a fix hard coded salt (key), before using bcrypt with the unique salt.
crypt() is a one-way string hash, not an encryption mechanism. To use an SHA-512 hash, you have to use the hash() function. Bcrypt requires a PHP extension. For storing passwords, why do you want to make them reversible, rather than just hashing them? That's less secure -- if someone gets your key and DB, they have all the passwords, but a table of SHA512 hashes is pretty useless.
Hashing first won't help. A bad password is one that is deemed more probable by an attacker and placed earlier in his list of passwords to try.
Bcrypt incorporates salt to eliminate pre-computed lookup tables (a Rainbow Table is one example). Why would an attacker build a rainbow table for a single record? No, when attacking a salted password, an attacker simply works through his ordered list of most likely passwords, repeating the hash algorithm to see if it matches.
How far he can work through that list depends on how long the hash algorithm takes to execute. Bcrypt controls that with the "cost" factor—12 in your example (which is okay, but probably the minimum I'd use). An extra SHA-512 round doesn't add anything to that. You are already performing 4096 expensive bcrypt iterations. Adding 1 cheap SHA-512 iteration is negligible.
If you choose the first password on the list, it will be broken in a fraction of a second. If you pick the billionth password, the attacker won't break it for a few decades.
bcrypt already uses salt, and what it's doing internally is quite a bit stronger than SHA512. Adding an iteration of SHA512 (and/or an extra layer of salt) on top of bcrypt will not give you a significantly stronger result. If the two functions interact in the wrong way, combining them in this way may in fact give you a hash function that is weaker.
I'm starting a website and I'm trying to decide how to encrypt user passwords to store them in a SQL database.
I realize that using a simple md5(password) is very unsecured. I'm considering using a sha512(password.salt), and I have been researching the best way to generate a useful salt.
I read numerous articles stating that a salt should be as random as possible to add entropy to the hash and it looks like a great idea. But:
you need to store the random salt along with your hash
given that an attacker somehow got access to your hashed passwords (and is trying to reverse the hash to plain text), it means he probably dumped your database, then got access to your random salts also
Isn't it obvious that the weird looking value next to the hash in the database is a salt? If the attacker can access the salt along with the hash value, how is that more secure?
Anyone has any expertise in that area? Thanks!
An attacker is "allowed" to know the salt - your security must be designed in a way that even with the knowledge of the salt it is still secure.
What does the salt do ?
Salt aids in defending against brute-force attacks using pre-computed "rainbow-tables".
Salt makes brute-force much more expensive (in time/memory terms) for the attacker.
Calculating such a table is expensive and usually only done when it can be used for more than one attack/password.
IF you use the same salt for all password an attacker could pre-compute such a table and then brute-force your passwords into cleartext...
As long as you generate a new (best cryptogrpahically strong) random salt for every password you want to store the hash of there is no problem.
IF you want to strengthen the security further
You could calculate the hash several times over (hash the hash etc.) - this doesn't cost you much but it makes a brute-force attack / calculating "rainbow-tables" even more expensive... please don't invent yourself - there are proven standard methods to do so, see for example http://en.wikipedia.org/wiki/PBKDF2 and http://www.itnewb.com/tutorial/Encrypting-Passwords-with-PHP-for-Storage-Using-the-RSA-PBKDF2-Standard
NOTE:
Using such a mechanism is these days mandatrory since "CPU time" (usable for attacks like rainbow tables/brute force etc.) is getting more and more widely available (see for example the fact that Amazon's Cloud service is among the top 50 of fastest supercomuters worldwide and can be used by anyone for a comparatively small amount)!
given that an attacker somehow got access to your hashed passwords
(and is trying to reverse the hash to plain text), it means he
probably dumped your database, then got access to your random salts
also
The whole point of salting is to defeat "rainbow tables":
http://en.wikipedia.org/wiki/Rainbow_table
See why a sufficiently long salt defeats any rainbow table under the section "Defense against rainbow tables".
how is that more secure?
It used to be more secure because it forced the attacker to try a, back then, very costly brute-force approach instead of an instant looked in precomputed rainbow tables. If you had a 64 bit salt, the attacker needed to have 2^64 precomputed rainbow tables instead of one... In other words: it made rainbow tables useless.
Note however that modern GPUs can crack billions of passwords per second making it mostly pointless for an attacker to store huge rainbow tables (instead of storing billions of hashes, simply compute them in a few seconds).
Nowadays you want to store your "passwords" using something like PBKDF2 or scrypt.
The strength of your hashed, salted passwords rely on all of the following factors:
The strength of the hashing algorithm
The randomness of the salt
The randomness of the password
Your system is as strong as the weakest of the above.
The questions below are from the sister site Security StackExchange. They discuss hashing, salts, PBKDF2, bcrypt, scrypt, and a few other things.
How to securely hash passwords?
Do any security experts recommend bcrypt for password storage?
There's also some previous discussion from here on StackOverflow as well:
Is BCrypt a good hashing algorithm to use in C#? Where can I find it?
In short answer to you question, a salt is a safeguard that makes it take a long time to recover a password in the event of compromise just as a hash is. If attacking one password, the salt won't make a difference. If trying to use a pre-computed dictionary or test many passwords at the same time, having a different salt for each entry will greatly increase the amount of work needed and generally make generating a suitable rainbow table infeasible.
Here's a good article on cryptography: http://www.javacodegeeks.com/2012/02/introduction-to-strong-cryptography-p1.html
See the section Real World Usage of Hash Algorithms, Scenario 1 for discussion of the salt.
I highly recommend using http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html to generate your salt
I am seeking advice on how to securely store passwords in MySQL using PHP.
Overlooking the limitations of PHP itself, I want to know more about salting, hashing, and encrypting these bad boys.
Obviously people will continue to use weak passwords unless forced to do otherwise, but it's how I am storing them that is important to me. My user's passwords are far more important to me than the database itself, and as such I want to keep them in such a way that it will be painstaking and monotonous for any script kiddie trying reverse. Obviously with due diligence just about anything can be defeated, but I wouldn't mind making this particularly bothersome.
There are two scenarios we are looking at.
The kiddie has a complete copy of the database.
The kiddie has a complete copy of the PHP used to craft the password, and the database.
Any and all advice on this topic is graciously appreciated.
Use bcrypt. If someone has the user table of your database, then they can use brute force/rainbow tables/etc to their heart's content. Even with salt, if you're using MD5 or some other fast-hashing algorithm (which aren't designed to solve this problem, by the way); it's just a matter of time before it can be cracked.
Any well-known and widely-supported hashing algorithm is going to have this same basic "flaw" (if you can call it that; it's really by definition). The difference is that bcrypt is slow as molasses when performing the hashing operation, rendering a brute force attack much less effective.
For an absolutely great discussion on the merits of bcrypt, the dangers of other approaches, and the difficulty of password security in general, read this thread. It has lots of comments by many people that are much more knowledgeable about this sort of thing than I am, and it should hopefully help you understand more of the issues at stake.
Assuming you're using username and password as authentication tokens you can safely store the following to ensure the data can't be compromised.
Username (in plaintext)
Salt (random string)
Salted Hash (sha1(username + salt + password))
Using the scheme, an attacker cannot use rainbow tables against you and the passwords are not recoverable by any (reasonable) means. (That is, as long as your attacker isn't the government)
Even though the attacker has the salt and hash pairs it's not possible to use rainbow tables because all the possible hashes will need to be computed anyway, using the salt that they've been given, so it's a brand new brute force attack for each user.
Even with the source code and attacker won't be able to get hold of the passwords because the strength/security is in the hashing algorithm, not your code.
Combine this with using bcrypt as per Donut's answer and you're really quite safe. That is:
Username (in plaintext)
Salt (random string)
Salted Hash (bcrypt(username + salt + password))
Taking advice from here, for added fun you can dynamically change your salt as well. For example, use different salts for usernames of different length, use the user's registration date as the salt. This makes it that even if someone DOES get to your database, they can't just re-generate the hash, they have to calculate a hash table for each salt that you used.
If your users are over the internet, OpenId would be one of your best options. http://openid.net/
If your users are on your network, can you do Integrated Security?
In other words.. do not store their passwords.
Usually "salted" passwords (like with bcrypt) mean that not the password itself is stored, but only something like
salt
hash(salt with password appended)
Now if the kiddie has your database (and of course, the code - there is no point in keeping the code secret), he/she can only guess passwords, calculate the salted hash, and compare. If the hash function is expensive (like bcrypt is), than guessing is expensive too.
It's simple
store(sha256("somesalt" + password));
And nobody will be able to reverse it :)
See also: https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512
I'm making a php login, and I'm trying to decide whether to use SHA1 or Md5, or SHA256 which I read about in another stackoverflow article. Are any of them more secure than others? For SHA1/256, do I still use a salt?
Also, is this a secure way to store the password as a hash in mysql?
function createSalt()
{
$string = md5(uniqid(rand(), true));
return substr($string, 0, 3);
}
$salt = createSalt();
$hash = sha1($salt . $hash);
Neither. You should use bcrypt. The hashes you mention are all optimized to be quick and easy on hardware, and so cracking them share the same qualities. If you have no other choice, at least be sure to use a long salt and re-hash multiple times.
Using bcrypt in PHP 5.5+
PHP 5.5 offers new functions for password hashing. This is the recommend approach for password storage in modern web applications.
// Creating a hash
$hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
// If you omit the ['cost' => 12] part, it will default to 10
// Verifying the password against the stored hash
if (password_verify($password, $hash)) {
// Success! Log the user in here.
}
If you're using an older version of PHP you really should upgrade, but until you do you can use password_compat to expose this API.
Also, please let password_hash() generate the salt for you. It uses a CSPRNG.
Two caveats of bcrypt
Bcrypt will silently truncate any password longer than 72 characters.
Bcrypt will truncate after any NUL characters.
(Proof of Concept for both caveats here.)
You might be tempted to resolve the first caveat by pre-hashing your passwords before running them through bcrypt, but doing so can cause your application to run headfirst into the second.
Instead of writing your own scheme, use an existing library written and/or evaluated by security experts.
Zend\Crypt (part of Zend Framework) offers BcryptSha
PasswordLock is similar to BcryptSha but it also encrypts the bcrypt hashes with an authenticated encryption library.
TL;DR - Use bcrypt.
I think using md5 or sha256 or any hash optimized for speed is perfectly fine and am very curious to hear any rebuttle other users might have. Here are my reasons
If you allow users to use weak passwords such as God, love, war, peace then no matter the encryption you will still be allowing the user to type in the password not the hash and these passwords are often used first, thus this is NOT going to have anything to do with encryption.
If your not using SSL or do not have a certificate then attackers listening to the traffic will be able to pull the password and any attempts at encrypting with javascript or the like is client side and easily cracked and overcome. Again this is NOT going to have anything to do with data encryption on server side.
Brute force attacks will take advantage weak passwords and again because you allow the user to enter the data if you do not have the login limitation of 3 or even a little more then the problem will again NOT have anything to do with data encryption.
If your database becomes compromised then most likely everything has been compromised including your hashing techniques no matter how cryptic you've made it. Again this could be a disgruntled employee XSS attack or sql injection or some other attack that has nothing to do with your password encryption.
I do believe you should still encrypt but the only thing I can see the encryption does is prevent people that already have or somehow gained access to the database from just reading out loud the password. If it is someone unauthorized to on the database then you have bigger issues to worry about that's why Sony got took because they thought an encrypted password protected everything including credit card numbers all it does is protect that one field that's it.
The only pure benefit I can see to complex encryptions of passwords in a database is to delay employees or other people that have access to the database from just reading out the passwords. So if it's a small project or something I wouldn't worry to much about security on the server side instead I would worry more about securing anything a client might send to the server such as sql injection, XSS attacks or the plethora of other ways you could be compromised. If someone disagrees I look forward to reading a way that a super encrypted password is a must from the client side.
The reason I wanted to try and make this clear is because too often people believe an encrypted password means they don't have to worry about it being compromised and they quit worrying about securing the website.
As Johannes Gorset pointed out, the post by Thomas Ptacek from Matasano Security explains why simple, general-purpose hashing functions such as MD5, SHA1, SHA256 and SHA512 are poor password hashing choices.
Why? They are too fast--you can calculate at least 1,000,000 MD5 hashes a second per core with a modern computer, so brute force is feasible against most passwords people use. And that's much less than a GPU-based cracking server cluster!
Salting without key stretching only means that you cannot precompute the rainbow table, you need to build it ad hoc for that specific salt. But it won't really make things that much harder.
User #Will says:
Everyone is talking about this like they can be hacked over the
internet. As already stated, limiting attempts makes it impossible to
crack a password over the Internet and has nothing to do with the
hash.
They don't need to. Apparently, in the case of LinkedIn they used the common SQL injection vulnerability to get the login DB table and cracked millions of passwords offline.
Then he goes back to the offline attack scenario:
The security really comes into play when the entire database is
compromised and a hacker can then perform 100 million password
attempts per second against the md5 hash. SHA512 is about 10,000 times
slower.
No, SHA512 is not 10000 times slower than MD5--it only takes about twice as much. Crypt/SHA512, on the other hand, is a very different beast that, like its BCrypt counterpart, performs key stretching, producing a very different hash with a random salt built-in and will take anything between 500 and 999999 times as much to compute (stretching is tunable).
SHA512 => aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
Crypt/SHA512 => $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21
So the choice for PHP is either Crypt/Blowfish (BCrypt), Crypt/SHA256 or Crypt/SHA512. Or at least Crypt/MD5 (PHK). See www.php.net/manual/en/function.crypt.php
Use SHA256. It is not perfect, as SHA512 would be ideal for a fast hash, but out of the options, its the definite choice. As per any hashing technology, be sure to salt the hash for added security.
As an added note, FRKT, please show me where someone can easily crack a salted SHA256 hash? I am truly very interested to see this.
Important Edit:
Moving forward please use bcrypt as a hardened hash. More information can be found here.
Edit on Salting:
Use a random number, or random byte stream etc. You can use the unique field of the record in your database as the salt too, this way the salt is different per user.
What people seem to be missing is that if the hacker has access to the database he probably also has access to the php file that hashes the password and can likely just modify that to send him all the successful user name password combos. If he doesn't have access to the web directory he could always just pick a password hash it, and write that into the database. In other words the hash algorithm doesn't really matter as much as system security, and limiting login attempts also if you don't use SSL then the attacker can just listen in on the connection to get the information. Unless you need the algorithm to take a long time to compute (for your own purposes) then SHA-256 or SHA-512 with a user specific salt should be enough.
As an added security measure set up a script (bash, batch, python, etc) or program and give it an obscure name and have it check and see if login.php has changed (check date/time stamp) and send you an email if it has. Also should probably log all attempts at login with admin rights and log all failed attempts to log into the database and have the logs emailed to you.
Everyone is talking about this like they can be hacked over the internet. As already stated, limiting attempts makes it impossible to crack a password over the Internet and has nothing to do with the hash.
The salt is a must, but the complexity or multiple salts doesn't even matter. Any salt alone stops the attacker from using a premade rainbow table. A unique salt per user stops the attacker from creating a new rainbow table to use against your entire user base.
The security really comes into play when the entire database is compromised and a hacker can then perform 100 million password attempts per second against the md5 hash. SHA512 is about 10,000 times slower. A complex password with today's power could still take 100 years to bruteforce with md5 and would take 10,000 times as long with SHA512. The salts don't stop a bruteforce at all as they always have to be known, which if the attacker downloaded your database, he probably was in your system anyway.
Here is the comparison between MD5 and SHA1. You can get a clear idea about which one is better.
MD5 is bad because of collision problems - two different passwords possibly generating the same md-5.
Sha-1 would be plenty secure for this. The reason you store the salted sha-1 version of the password is so that you the swerver do not keep the user's apassword on file, that they may be using with other people's servers. Otherwise, what difference does it make?
If the hacker steals your entire unencrypted database some how, the only thing a hashed salted password does is prevent him from impersonating the user for future signons - the hacker already has the data.
What good does it do the attacker to have the hashed value, if what your user inputs is a plain password?
And even if the hacker with future technology could generate a million sha-1 keys a second for a brute force attack, would your server handle a million logons a second for the hacker to test his keys? That's if you are letting the hacker try to logon with the salted sha-1 instead of a password like a normal logon.
The best bet is to limit bad logon attempts to some reasonable number - 25 for example, and then time the user out for a minute or two. And if the cumulative bady logon attempts hits 250 within 24 hours, shut the account access down and email the owner.
Use argon2i. The argon2 password hashing function has won the Password Hashing Competition.
Other reasonable choices, if using argon2 is not available, are scrypt, bcrypt and PBKDF2. Wikipedia has pages for these functions:
https://en.wikipedia.org/wiki/Argon2
http://en.wikipedia.org/wiki/Scrypt
http://en.wikipedia.org/wiki/Bcrypt
http://en.wikipedia.org/wiki/PBKDF2
MD5, SHA1 and SHA256 are message digests, not password-hashing functions. They are not suitable for this purpose.
Switching from MD5 to SHA1 or SHA512 will not improve the security of the construction so much. Computing a SHA256 or SHA512 hash is very fast. An attacker with common hardware could still try tens of millions (with a single CPU) or even billions (with a single GPU) of hashes per second. Good password hashing functions include a work factor to slow down dictionary attacks.
Here is a suggestion for PHP programmers: read the PHP FAQ then use password_hash().
Let's assume the next point : the hackers steal our database including the users and password (encrypted). And the hackers created a fake account with a password that they know.
MD5 is weak because its short and popular and practically every hash generation without password is weak of a dictionary attack. But..
So, let's say that we are still using MD5 with a SALT. The hackers don't know the SALT but they know the password of a specific user. So they can test : ?????12345 where 12345 is the know password and ????? is the salt. The hackers sooner or later can guess the SALT.
However, if we used a MD5+SALT and we applied MD5, then there is not way to recover the information. However, i repeat, MD5 is still short.
For example, let's say that my password is : 12345. The SALT is BILLCLINTON
md5 : 827ccb0eea8a706c4c34a16891f84e7b
md5 with the hash : 56adb0f19ac0fb50194c312d49b15378
mD5 with the hash over md5 : 28a03c0bc950decdd9ee362907d1798a I tried to use those online service and i found none that was able to crack it. And its only MD5! (may be as today it will be crackeable because i generated the md5 online)
If you want to overkill then SHA256 is more than enough if its applied with a salt and twice.
tldr MD5(HASH+MD5(password)) = ok but short, SHA256 is more than enough.
An md5 encryption is one of the worst, because you have to turn the code and it is already decrypted. I would recommend you the SHA256. I'm programming a bit longer and have had a good experience. Below would also be an encryption.
password_hash() example using Argon2i
<?php
echo 'Argon2i hash: ' . password_hash('rasmuslerdorf', PASSWORD_ARGON2I);
?>
The above example will output something similar to:
Argon2i hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0