This question already has answers here:
Password hashing, salt and storage of hashed values
(4 answers)
Closed 9 years ago.
How to implement an algorithm for storing and comparing hashes in 2048bits for passwords with random salt for each password with PHP?
EDIT 1:
I guess I was not clear enough in my question. What I mean is that I will not make my encryption algorithm. But how could store a password and salt. Being the random salt for each password. Well, it would not be sensible to store the salt along with the password in the database.
EDIT 2:
That would be a good approach?
1) user enters their password,
2) system generates a hash of the password,
3) system generates a password for this salt (I use time ()?)
Being the random salt, how and where could store the salt to the password? Please, I would not want to store the salt along with the password, because I think this is not so sure.
So after the stored password and the salt of the same when the user logs in, I get the password hashes stored along with the salt and compare it to the hash of the password supplied with the salt saved.
Where to save the salt?
This would be a good approach to do this?
"Well, it would not be sensible to store the salt along with the password in the database."
"Because if my database is compromised and someone has access to this data, it will have the salt for each password with each password. And that is not correct. Well I think I just would not make sense to use a salt and give it to brute force along with the password. Because it would be correct?"
These core assumptions are wrong. The point of a salt is to add a unique element to each password so two identical passwords won't hash to the same hash value. The salt is not secret. I repeat: the salt is not secret. The secret is the password, the salt just adds the uniqueness. An attacker will have to brute-force a password by trying every possible combination of characters and comparing the result to the hash value. If he also knows the salt, he will still have to do exactly that.
If the attacker successfully brute-forced the password "foobar" without salt, he has brute-forced every password "foobar". If you add a unique salt and the attacker successfully brute-forced the password "foobar" + salt, he has only brute-forced that one password. He'll have to attack every other password "foobar" separately, since they all hash to a different value, thanks to the unique salt.
That is the point of a salt. Yes, it would be even better if you could keep the salt secret as well, since then the attacker would have to essentially brute-force a value many times longer. But that's infeasible, since you need access to the salt to confirm the password as well. If you need to have access to the hash and salt, then an attacker who has access to the hash likely also has the same access to the salt. It also does not detract from the security if the attacker has access to the salt.
Related
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.
This question already has answers here:
Secure hash and salt for PHP passwords
(14 answers)
Closed 8 years ago.
I have read tons of questions and tutorials about encrypting a password, and while I've learned a lot, nowhere did I find an answer to this.
I want to use crypt() for hashing a password that I will store on Database. I also know I need to use a salt so it works properly, and I've read that the best way to generate a random salt is by using this or something similar.
If I understood correctly the process is this:
User enters a password
Random create a salt
Hash password and salt
Store result in database
But then how do I recover the salt when user tries to login?
User enters his password
I somehow add his own unique randomly generated salt
Hash both of them together
Compare it to hashed salted password stored in Database.
In a few questions I've found, one of the answers was to store the randomly generated salt on the database. But I thought the whole purpose of salting was to be more secure, if an attacker got access to my DB he would see the 'salt' fields and even if my passwords are encrypted he would gain easy access to accounts.
Other answers said that the 'salt' is prepended to the password when using crypt() so there is no need to store it in a separate field. My question is, how do I get access to it? Is there some function that does this and I'm totally missing?
You store the salt in your db, along with the hashed password, i.e. hash(salt+password).
If your database gets compromised and someone gets all the hashes and the salts, they cannot run a rainbow table attack against your hashes - they will need to brute force each hash. With a good hashing algorithm, the brute force attack is unfeasible.
What is a rainbow table attack?
Lets assume a generic hashing algorithm, hash(f).
I, as an attacker, precalculate common passwords (f) and their hashes (hash(f)). Now, when I get your unsalted database of hashes, I just need to look through your database for hashes that match my precalculated table (rainbow table).
For example, if my rainbow table stores that for f = qwerty, hash(f) = someRandomHash, I look through your database for someRandomHash and as soon as I find it, I know that user's password is qwerty.
However, if you salted your passwords, when a user set his password as qwerty, you calculated his hash as hash('saltqwerty), which means, you did not calculate his hash as someRandomHash but instead as someRandomSaltedHash. This renders my rainbow table completely useless.
I am left with no choice but to brute force your table. I know the salt, but I don't know the password, so I have to calculate hash(salt+password) for every possible permutation and combination of password. With a slow enough hashing algorithm, this can take centuries (worst case).
How do you login a user?
User submit his user_id and password. You query the database for the salt for that user. Then you compute hash(salt+password) and compare against the hash stored in your database.
You can safely store a hashed password and a salt in the same database - the idea is that since the salt is different every time, even the exact same passwords will be stored differently in the database, which virtually eliminates brute-force lookup weaknesses associated with things like md5-encoded passwords.
Out of an obvious mass confusion, if you're able to use PHP v5.5.0 or higher, password storage has become remarkably easier with the use of password_hash and password_verify.
As an additional benefit, these functions don't require you to have separate password and salt fields in your database - you can simply store the returned password_hash value and use password_verify with the clear-text password to validate.
I don't know a lot about high level security DB, but how about this?:
hashedPassword = hash(UsurID+GivenPassword)
So, at logon time, youget first the User Login, and his ID, and then the given password to compare with the hashedPassword tha is already in DB.
As I said, I dont know if this will increase security, but at least it makes all passwords differents, doesn't?
Anyway, I'm still learning too.
My database stores unique salts for every user.
I'm creating a login script in php for an application where each user has it's own unique salt and here's how I plan to implement the login.
User enters details and sends them
Username is sent and script check if it exists
If it does then returns the salt for that user otherwise general error is returned
I need the script to return the salt for that user because otherwise how would my app verify that the submitted password is correct when it cannot hash the password without the salt and send it back?
Now here's what I'm unsure about. Does it matter whether the salt is encrypted or not because a hacker could just see what it is and see the password hash and maybe could do something with it. Should I encrypt the salt before I send it?
Maybe I'm not understanding/overlooking something in the replies below.
Advice needed please.
It doesn't matter if your salts are hashed or left as plain strings - the important point is that salting a password prevents the direct use of dictionary/rainbow table attacks to brute-force crack passwords. An added advantage is that each user has a different hashed password as a result.
Salts are randomly generated string that are created server-side and don't involve any kind of transmission to or from the browser.
On your server:
// Password from form
$pw = $_GET['password'];
// Generate salt using unique values
$salt = (rand(8).$registration_date.$username);
// Password to be hashed
$pwthb = ($pw.$salt);
If a hacker gains access to your databases, then your game is over in the majority of cases as you need to store the initial random salt to hash it for comparison.
A simple example:
User enters initial password in browser upon registration
On your server, password is combined with a unique salt, hashed and stored as password in DB
Salt is stored in DB
Note: hashing can be done using PHP or using MySQL/DB functions
When the user returns:
User enters password in browser
Grab salt from DB and combine with the password entered
Hash password+salt and compare with stored/hashed password
If they match: authenticate
In terms of further reading, It's probably worth looking over the following:
Is encrypting a salt value with a password/plaintext a viable alternative to straight up hashing?
The necessity of hiding the salt for a hash
How store salt in distributed environment
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 looking into building a login system and after reading the php manual when you pass a 2 digit salt to the crypt() function it returns a hash string, and the first 2 digits of the string are the salt that you used.
example:
$salt = "kr";
echo crypt("mysecret",$salt); //returns "kreOI.F7eOQMY"
My first thought was, wouldn't this help someone who is trying to reverse your hash?
I looked up salt on wikipedia which said:
For best security, the salt value is kept secret.
So I do not understand why then would the crypt function return all hashes prepended with the salt value used?
Is there a reason for this? Should this be a security concern?
The author of the Wikipedia article is conflating salt with the idea of search space, implying salt is a way to deter brute force attacks. Security is not improved by confusing these ideas; someone who can't recognize and delineate these two issues is not a credible guide.
The purpose of salt is to thwart pre-computed lookup tables (like a Rainbow table). Salt prevents an attacker from trading "space" for "time." Every bit of salt doubles the storage requirements for a table; a two byte salt makes a big (65536 times) difference, but eight bytes would require non-existent "yottabyte" storage devices for lookup tables.
Assuming that the salt cannot be kept secret encourages better key-strengthening and password selection, and this leads to more secure system.
However, recent recommendations from NIST encourage the use of an additional, secret "salt" (I've seen others call this additional secret "pepper"). One additional iteration of the key derivation can be performed using this secret as a salt. Rather than increasing strength against a pre-computed lookup attack, this round protects against live dictionary attacks. In this way, it's more like the large number of iterations in a good key derivation function.
This secret serves no purpose if stored with the hashed password; it must be managed as a secret, and that could be difficult in a large user database.
Brute force attacks are best prevented by key-strengthening (applying the hash function thousands of times), and password selection rules (require longer passwords, reject blacklisted entries, etc.), but a "pepper" provides an additional layer of defense.
I should comment that Crypt is not as bad as Marc B makes it sound, and may in fact be the easiest way to good hashes, as long as you don't rely on its weaker schemes like MD5.
See:
How do you use bcrypt for hashing passwords in PHP?
http://uk.php.net/manual/en/function.crypt.php
http://www.openwall.com/phpass/
Yes, the salt is supposed to be kept secret, but then so is the password hash. It's perfectly acceptable for them to be kept equally secret in the same place. To check a password against the hash, you have to combine the salt with the password and then check it against the hash. So, any user or process with the right to see the password hash should also have the right to see the salt, since the password hash by itself is not useful for checking passwords (unless you're going to brute-force the salt).
The purpose of the salt is so that if two different users have the same password, they'll hash to different things. This also means that dictionary attacks are much more complex because you can't just hash all likely passwords and then check them against a list of user password hashes to find multiple user's passwords. Instead you have to try passwords for an individual salt to find one user's password or try all combinations of likely passwords with multiple salts in order to find hits. But knowledge of the salt, by itself, doesn't mean you can reverse the password hash. It just means that you can do a dictionary attack on the password hash.
If you can find a way to keep the salt more secure than the hash value, it certainly wouldn't be a bad thing, but it's hard to see how this is feasible when any program which needs access to one needs access to both.
The crypt() function is obsolete. It was used to hash passwords for old-style Unix systems, before shadow password support came along. The salt was there to increase the complexity of brute forcing the password. However, since the salt was randomly generated by the password subsystem, it had to be stored in the clear so any future password actions would work. If the salt had been embedded into the password before crypting, there would be no practical way to verify a password - you'd have to try every single possible salt whenever a password check was done - highly impractical. So, the salt was prepended to the crypted password, so you could pull it out again for future use.
crypted password: xxabcdefghijklmn
^^- salt
^^^^^^^^^^^^^^-- crypted pw
if ('xx' + crypt('xx' + password) == 'crypted string') then
password is ok
endif
These days, crypt() is the security equivalent of a cereal box decoder ring. There for historical purposes, and low-security "who cares if it's cracked into" storage. For any modern password usage, you'd be better off with more modern hashes, such as sha1/sha256/md5. And even md5 is considered broken these days, sha1 has cracks around the edges, and (last I checked) sha256 is still secure.
The salt is appended to the has so that you will know which salt to use when you get the password and want to see if it matches the hash. The idea here is to use a different salt for every password so that someone cannot precompute a hash table.
You could also append a second salt to every password (the same for all) and not tell anyone what it is.
PHP crypt inherits this behaviour from the UNIX crypt() function, which was used for generating password hashes in the UNIX passwd file. It's necessary to store the salt somewhere, or you can't verify later that the password is correct. For the passwd file, the simple behaviour was just to prepend the salt (always two characters) to the start of the crypted password, which makes it simple to store it in a single field.
The statement that the salt value should be kept secret is open to misinterpretation. For best practice you should not publish your salts, in the same way that you should not publish your password hashes. Giving an attacker the hashes and salts makes it easy for them to run a brute-force attack without generating suspicious traffic to your system. However, the system should still be secure even if an attacker can see both salt and hashed password.
In fact, there's nowhere you can store the hash that couldn't, in principle, be compromised by a hacker in exactly the same way as the hashed passwords. If the password-checking code can access it, then you have to assume that someone who's compromised the system could get access to it as well.