I'm working on a site which is (try to be) super secure. I read a lot about password hashing and using salts, but not everything is clear to me. I would like to use sha-256 hash algorithm with salt. I know about salts that all of them should be unique per-user per-password.
I'm wondering what if I use the password as salt too? Hash the password with sha256 and then hash it with an other algorithm and use it as salt. In this way I don't have to store the salt in the database. Is this possible? or should I generate a random string?
No, that is still a one-way algorithm.
If another user uses the same password the hash value will be the same as the hash of the pass of the first user. That misses the point that hash values must be different for each user and each pass entry.
I suggest to use the date of registration of a user (for example) as salt. This way for each user and each pass the hashing algorithm will be different (ok, if two users have the same pass AND the same reg. date it will be the same).
Or maybe you can use user id for salt, or some combination between user id and reg.date and user name.
Edit:
Your approach is actualy better than hashing with known algorithm without salt, but worse than hash+propper salt.
What you do is just applying custom hash function of your own. That can't be easyly brute-forced without knowing the custom algorithm, but is vunerable to other attacks.
And I suggest not placing a table with name "SALT" in the db, for if DB is hacked the attacker wii get the passwords AND the salts for them.
Related
I understand that bcrypt is more secure than other methods but still puts you the same situation where you need to salt passwords!
If the salt is included in the hash string it's not needed to store it separately in the DB. Everytime I need to create a new hash, meaning a new salt as well, do I have to get all the passwords, extract the salts and check the new one doesn't exist already against my DB passwords?
Wouldn't be easier to store directly the salts separately for easy compare? If yes then I don't get:
the point of storing the salt in plain text
why bcrypt is more secure than manually use sha256 with salted passwords
I'm actually going to disagree with Curtis Mattoon's answer on a couple of things.
When you hash using bcrypt, the salt is stored directly inside the hash, so you don't need to store it separately. I'm not sure what he means by not having to store it at all, because the hash without the salt is completely useless. The salt is needed to verify the password against the hash.
I agree on this point. If you are updating one password, you don't need to update them all. In fact, it would be impossible because you (hopefully) don't know the passwords for any other users.
You don't need to go through pains to get a unique salt. If that were the case, you could use uniqid, but the problem with that is its output is predictable. Predictability is a bad thing in cryptography. Instead, what you want to do is use a pseudo random salt as close to random as possible (i.e. using /dev/random instead of /dev/urandom). If you have a billion users, you may get one or two that have exactly the same salt, but seriously, is this such a big problem? All it does is doubles someone's chance of brute forcing the password for those two particular passwords out of a billion, and I doubt it's even that high of a chance of a collision occurring. Don't strain yourself over this. Make the salts random, not unique. Using things like last login time or IP address is only going to take away from randomness.
As for a comparison between SHA512 and Blowfish, see here SHA512 vs. Blowfish and Bcrypt
This site seems to do a decent job at a brief explanation: http://michaelwright.me/php-password-storage
Quick answer:
1) You don't need to store the salt.
2) You don't need to update all the hashes, if you use a unique salt for each password.
3) I'm no crypto expert, but when you're using a unique salt for each user/password, an attacker would have to use a different set of rainbow tables for EACH user. Using the same salt value across the site means that every user's password would be susceptible to the same hash tables. In the past (for better or worse), I've used a function of the user's last login time and/or last IP as the for their password's salt.
e.g. (pseudocode) $password = hash(hash($_POST['password']) . hash($row['last_login']));
4) I'll defer the "Why is bcrypt better?" question to someone more knowledgeable about such things. This answer may help: How do you use bcrypt for hashing passwords in PHP?
I want to update my password setup that is currently using just MD5.
Now what I would like to do is use something stronger (maybe sha256) with unique salt per user.
The question is about the salt storage.
Do I go with storing the salt in its own column in the database?
Then hash salt + password and when it comes to login, call the salt and password from the database, to make one.
Or do I go the way of making a salt, by using the username, email and timestamp which would also give me a unique salt per user?
I am wondering, if someone got a hold of the database with salt as a column, they would know the salt for each user, then they could crack the password.
The salt is not a secret, it can be stored plaintext together with the hash. It is not even necessary to have a second field in the database. If you look at PHP's crypt() function, you can see, that the salt will be included in the hash value itself.
It's the job of the salt, to make already existing rainbowtables useless, because a rainbowtable has to be built for one specific salt. Using a different salt for every hash will prevent rainbowtable attacks, because you would have to create a rainbowtable for each hash. That's why it is not necessary to keep the salt secret.
I would recommend, that if you want to improve your password hash system anyway, you do it right, with a hash function that is slow. The article password hashes with bcrypt explains the important points of generating a hash for passwords.
Generate a salt per password, not per user.
Use a random (unique) salt, not one derrived from other parameters.
Use a slow hash function.
Last but not least, don't be afraid of doing it correctly, the code of your application can be as easy as your current implementation with MD5.
Forget MD5 or SHA. Use Bcrypt. (Blow Fish Crypt) Comes native with PHP 5.3 and above. (crypt method 2a) it is more secure and processes slower.
When using Bcrypt the salt is stored together with the hash in the same feild . There is no reason for a seperate one.
http://php.net/manual/en/function.crypt.php
Just reading on another post and someone says the salt is not a secret and can be stored a database column. So that answers my question
I am using following way to encrypt user's passwords which is AES Encryption. I just want to know is this a good practice or is there any other method should I follow. Because someone made me confused saying "Why don't you use "SALT". Can I use SALT AES Encryption? with Bellow is a sample query I am using.
INSERT INTO user(id,passowrd) VALUES (1,AES_ENCRYPT('mypassword','key'));
I hope your database column isn't named "passowrd".
That aside..
Salt isn't an encryption method, it's a random bit you need to add to each password before hashing to protect against dictionary attacks.
You should not be storing user passwords using AES encryption, which is reversible. You don't care what the user's password is, only that they know it: so don't store the password in a reversible form.
Instead, you use a secure one-way hash, such as SHA256 or even bcrypt, of the password plus some random data. This random junk, the "salt", is generated for each user and appended to the password before hashing. It is then stored in the database along with the hashed data to enable you to compare the passwords later.
This way, an attacker with what's called a rainbow table (a big dictionary of hash-to-plaintext mappings) can't come along and see "oh look, Joe User decided to make his password 'password'!". This also protects against someone brute-forcing all the passwords in your database, since if each account has its own independent salt, each password must be independently attacked.
You wouldn't use "SALT" with AES, typically it's used with SHA.
Great details and explanation can be found at:
https://stackoverflow.com/a/4351749/1232478
A salt is a sequence of characters added to a string about to being hashed, so it's harder for an attacker to obtain the original string.
However, for a cipher algorithm that is not based on hash, a salt isn't necessary, because the attackers will obtain anyway the original string with the salt, and it's just needed logic to remove it.
With AES_ENCRYPT the key you're using IS the salt. I prefer one-way hashes like MD5 or SHA, but many like decryptable passwords like you're storing.
I've been reading a bunch of stuff about security and I'm just now starting to try and play around with the code. I want to use MD5 encryption with a salt. I ran across this nifty PHP script with random salt:
substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',5)),0,10);
It randomly generates some characters as salt, but then I was thinking: How would I go about checking logins? Do I remove the salt, or should I store it in the database?
You shouldn't be using MD5 for password hashing. See How can I store my users' passwords safely?
To answer your original question, the salt is stored alongside the HASHED password in the database. The salt is not meant to be secret if the hashed password is discovered. Its purpose is to prevent attackers from using rainbow tables.
Store it in database. Otherwise you can't compare password provided by user with hashed one.
Some even regenerate hash (with new salt) upon each successful login of given user, although commenters below argue this is not the best idea (see comments)
Okay, so salts are used for both one-way hashes and encryption. They make it harder to reverse the encryption or the hash. I think it's easier to draw the point out with hashes, so I'll write from that point of view, but the principles apply to encryption in general.
Imagine that you're saving passwords. One of your users chooses the word "kiwi" as a password. Because storing passwords in plain-text is stupid, you don't want to do that. You want to hash the password.
But, those pesky hackers out there have compiled huge databases of hash look-up tables. (Check this one out!)
So, how do we foil the hackers? By salting the user's input! The salt is a random string (or set of bits, properly) that is cryptographically combined with the user's input to produce a more secure hash.
For example, if the string to be hashed is still "kiwi" and our salt is "5m3d", a simple salt mechanism might concatenate the two into: "kiwi5m3d". The hackers probably have "kiwi" in their database, but probably don't have "kiwi5m3d". A good salting system will probably perform a much more complicated function than this.
So now the hackers need a new look-up database for each possible salt. Using a random salt means that the hacker will have to do a full-on brute force attack, rather than recycling previous computations or using someone else's look-up table.
You could choose a different salt for everything, or the same salt for all the things on your site. A different salt of each entity necessitates a new brute force attack for each entity, but it can make implementation more difficult because each salt must be saved, rather than having one global salt (which, for data which is already somewhat random, e.g. passwords, should be sufficient).
In the case of encryption, look-up tables are still a possibility, but the data to be encrypted is generally varied enough that they're not feasible. So it becomes a game of playing "guess the password". It's easy to guess "kiwi" and hard to guess "kiwi5m3d".
You will have to save the salt somewhere, because it's the only way to "know" what's been hashed or encrypted. In the case of a hashed, you compare the user's original hash against the salted hash of their input. In the case of encryption, you need the salt to decrypt the data.
Where do you go from here?
First, don't use MD5. I gave you a link to an MD5 look-up database above. The function's increasingly considered to be weak. The sha class of algorithms is a better choice.
Second, make sure you choose a good salt. Longer and randomer is better. Computers are kind of bad at generating random data. This site could be one good choice and has a pretty good break-down of how it generates its random numbers.
Third, consider salt algorithms. Simple concatenation should work, but maybe HMAC (something I don't know much about) would be better.
You would have to store it in the database, otherwise you would not have anything to compare it to. The thing to remember with using a salt, is that the complexity can vary and without knowing what the salt is, the likelihood of it being brute forced hack is dramtically decreased.
Example:
$password = "banana";
$salt = "a12dsfg33B1cD2eF3G"; # Can be any assortment of characters
$password = md5($salt.$password);
Then you would just attach the same salt (would have to match to work) and pass the same function to your login script that combines the salt and the supplied password. You would then check that to the value in your database to authenticate the user.
Do not invent your own password-hashing scheme, however nifty it may look. Having a secure system is hard because you cannot really test for security. What you need is the following:
For each password instance, a random salt of sufficient length is created.
The random salt is stored along the hashed value; you will need it to verify the password afterward.
The password hashing process must be (configurably) slow, with many (many) nested invocation of whatever hash function is internally used.
Preferably, the internal hash function should use operations which are efficient on a PC but slow on a parallel architecture (a GPU).
Such a thing exists, it is called bcrypt and you can get it in PHP with the portable PHP password hashing framework.
So I've been reading a lot about encryption in PHP. So much that I am not sure exactly what's a really good method to securely store login information.
However, the following function is what I came up with:
function loginHash($username, $password){
$salt = str_split($password,(strlen($password)/2)+1);
$hash = hash('whirlpool', $username.$salt[0].'centerSalt'.$salt[1]);
return $hash;
}
Am I doing it the right way? It's used for authenticating a password combined with a username, and the ability to compare the generated hash with the one stored in a database to verify a login.
Encrypting != Hashing. They both are generally accepted to be in the category of Cryptography, but when something can be encrypted, it can be decrypted, which is not the case in Hashing. Hashing is just hashing, and that's it.
The salt is indeed not properly constructed. It should be x-bytes read from /dev/urandom with a fopen() call. For example, 16 bytes of salt is what I personally use. This prevents rainbow table attacks effectively.
To make things more secure, use a secret key, too. For example:
$hashedPassword = hash_hmac('whirlpool',$password.$salt,$key);
The $key is simply random data. You could generate a 64 kB file, for instance, that is called "key.bin" in a hidden folder above the document root and use file_get_contents() before the hash process.
Why to use secret keys? If you store the hashes and salts in a database and the key in the filesystem, then this prevents anyone from cracking your hash if they get their hands on your stored hashes and salts. So, an attacker would need to crack into both the database and the filesystem to crack your hashes, but notice that it's pointless for anyone to crack your hashes anymore if they have already cracked your whole application, which implies that your hashing scheme is good.
My advise is to never, never, never write your own encryption and hash functions. Even experts do it wrong all the time, so dont try it yourself.
Ive heared that phpass (Openwall) is a nice hashing framework, i'd suggest you use that.
They use salts in their hashes and have quite some parameters to tweak the hash.
You're not actually using a salt.
Salt is a randomly generated string that is included in the input for your hash function. As such, it will be different every time.
The idea is that you generate a salt when a user stores a password, and that this salt is included in your data storage. When authenticating, you retrieve the salt and the stored hash, you prefix the given password with the stored salt, and hash the two together. Then compare the result with the stored hash.
I think the above code checks the two boxes.
Avoiding rainbow table attacks (via Salts)
Secure Login
using salt solves two problems:
rainbow tables: rainbow tables are just precalculated hashes, stored with the source value. by comparing the hashes, you get the unhashed value (password). by adding salt you got another layer of complexity - the attacker must know the salt for generating a custom hashing table.
difference of hashed values: without salt, the same 2 passwords generate the same 2 hashes. now it's easy to see if two users use the same password (the weak point here is about the same as with the rainbow tables, but still). that may not amount to much, but is still a point of concern.
additionally, you shouldn't use fast algorithms for password hashing. md5 is fast, sha is fast. the slower, the better.
the matsano chargen blog is a good (and funny) resource for hints and pointers regarding security.