Is there any benefit to using:
sha1($long_unpredictable_randomly_generated_salt.$password.$global_salt)
over
sha1(sha1($username).$password.$global_salt)
The unique salt is obviously stored in the database, while the global salt is in a configuration file on the server.
I know the purpsoe of a salt is just to be unique, and prevent pre-calculated hash tables.. so I see no reason the long hash generated by sha1($username) is not good enough.. but as security is very important, I thought i'd ask for informative advice here from somebody who may know better :-)
The disadvantage is that the username is mostly known, so when someone knows this 'formula' you made up, he can just calculate sha1(user_to_hack) and this part won't have any additional benefit. In fact, it won't matter much if you use sha1(username) or just username in this case.
In the other case, you're using a value that is not exposed, so even when someone knows your formula (which everybody knows now), he'll still needs the value of that unique salt too before it's any use to them, so they'll need to get to your database. I assume you're making up a unique salt for each user?
You'll probably need to get data anyway, so the unique salt is probably faster too, because you won't need to calculate the hash over username.
But anyway, both are pretty safe, but only if you implement the actual login procedure well. I wouldn't worry about which one to use right now.
Related
Currently I'm just fooling around with PHP, but I came across an idea I want to expand on and need to know how secure it is in your opinion, and how I can improve it to make it acceptable for practical use.
This is how I store the passwords in the database:
plain text password -> hash password (I use whirlpool, but any method will practically work)->
shuffle/scramble the hashed password (with the str_shuffle() function).
I store the users password in the database like so, to make sure if the database is compromised, it would make it impossible for the attacker to reverse the broken password hash inside the database. (Because how can you reverse in a sense, random text that use to be a hash? - Although I'm sure you can create a list of possibilities by comparing a list of hashes that share the same chars.)
The way I check if the users password they entered on the login form is correct (compared to the broken hash in the database) is by counting the individual letters+numbers (a-f & 0-9) in both strings/passwords , and see if they match up, and if they do, I assume they're correctly logged in.
And again, I want to know how secure this is in your opinion, and how can I improve it to make it acceptable for practical use. (If possible.)
& I would also like to try my best to avoid a "reversible" hash. (i.e the idea of creating my own way of ensuring the passwords match, I want to make it more of an A best guess Assumption, to completely help ensure it will be impossible for an attacker to reverse the passwords in the database.
& Yes I know this is stupid because it most likely causes more security flaws rather then helps fix them. But this is just something I'm fooling around with, and maybe hope to make it practical.
OTHER INFO:
1) Passwords are stored with unique salts (so not 1 account shares the same salt)
2) Password salts are always changing (Each time a Successful Login happens with a users account, it will change the users salt in the database. I do this to change the hash in the datbase, causing a password collision to be less frequent (hopefully) & also to prevent unwanted users from using the same incorrect password multiple times to login (If they manage to come across one, only way to achieve this is by bruteforce or 'guessing' which any login system is vulnerable to).
When I say password collision, I mean the slightest chance that the word "hello" & "blue" share the same exact char count (as I explained, I count the individual chars + numbers, and compare them, to ASSUME its the correct password.)
3) I will also MAYBE keep the first 3chars/numbers of the hashed password unaffectedd by the str_shuffle, to also help ensure the passswords are correct. (By creating 2 checks, 1) check if both strings share the same FIRST 3 CHARS/Numbers & 2) Then compare the count of chars in each string. (Hoping to make password collisions, again, less frequent).
4) Obviously other security measures will be added (i.e max login attempts, captcha , etc.. to help protect against automated bruteforcing, to make it harder for a hacker to find a possible password or the real password.
I have made a successful PoC of this, and it works like a charm, although I have yet to test the PoC against a Dictionary Attack / Brute Force Attack, to see the chances of password collisions. & How frequent they are.
If I stated a lot of 'useless' information, ignore it. I'm just trying my best to explain this reasonably.
This seems terribly ineffective and insecure to me.
Most notably: Collisions. You mentioned that already in Other Info.
Just checking for the count of characters in the hashed & scrambled lets collision probability go through the roof. You enable one password to be also valid for all permutations of its hash. Considering the length of 128 characters in a whirlpool hash, this is a veeery large number.
So, basically, by allowing this, you allow a would-be bruteforcer to check many many thousand passwords at once, by entering a single one.
They will not gain permanent access to the system, since you said you alter the hash after each login, but the probability that they gain access ONCE is increased substantially.
Concerning the altered salt... how do you do that? I can't think of a way unless you apply the salt after hashing instead of before, which is not how a Salt works in hashing.
If you want to make it more secure then just use multiple hash iterations. Store the hashed password and the number of hash iterations. Every time the user logs in hash the hash again, store it, and increase the iteration count. This will change the stored hash sufficiently without introducing too many cryptographic weaknesses.
Your shuffling scheme will make the password less secure. Comparing the number of instances of letter and numbers after a shuffle increases the chance of two people having the same password value (collision, as you said).
The re-salting is something you could use. Each time the user successfully logs in, you can re-salt the password and save it again. This could be even better if you modified the PHP password procedure to use a hi-res time value, increasing the unique-ness. Essentially you're continuously rotating the salt of the password. You would have to save the clear password, compare its hash to the saved one, re-salt and hash the clear password and save again.
The output of a cryptographically strong hashing function is for all intents and purposes already pseudo-random. Attempting to add entropy by scrambling it does nothing. It does nothing to make the hash less "reversible", since the only way to "reverse" a hash is by choosing an input, hashing it, comparing it with the hash; that's the same thing you have to do when logging the user in, it's the same thing an attacker has to do, changing the comparison algorithm does not change this basic operation. (As others have pointed out, your weakened comparison algorithm actually aids an attacker.)
The accepted way to deal with this problem is already sufficient:
Make sure your input is unique by salting it with (pseudo) random noise, this forces an attacker to do actual brute force hashing.
Choose a hash that is slow (preferably bcrypt or scrypt, with a high enough cost factor that makes it feasible for you to do once, but infeasible for an attacker to do billions of times), this makes it computationally infeasible for an attacker to brute force a hash in his life time.
If both steps are done correctly, it's already infeasible to "reverse" a hash. No additional mind games needed.
Don't fiddle around with your idea any longer. It is insecure.
There are only about two ways for password security that provide a sufficient level of resistance against tampering:
Use a hardware security module executing something like HMAC-SHA1. The module is external hardware, the outside world does not know the internal secret (only available by physical access to the module) inside the module, and without that module the generated hashes will never be reconstructed. Being dedicated hardware with a "fast" hashing algorithm makes this a viable solution for lot's of password checks. See http://en.wikipedia.org/wiki/Hash-based_message_authentication_code for details.
Use very slow hashing algorithm. Things like "scrypt" or "bcrypt" will execute very slowly, thus hindering the fast bruteforce scan of list of passwords against a list of known hashes. PHP only has support for "bcrypt" at this time.
You may wonder why you should use external hardware encapsulating a secret. Simple: Anything that is accessible from the machine that is doing the hash can be stolen. Stealing the secret is like using the same salt (or none at all) for all keys: You end up "only" having a very fast hash algorithm with every other component known, and can start bruteforcing passwords right away.
So if there is no dedicated hardware, the only other option is a slow password hash algorithm.
There is a solution for PHP: password_compat is a library that reimplements the PHP password hash API for versions before PHP 5.5. If you are already using 5.5, you simply use these functions.
I made a website time ago. Raw php with SQL. Now I am doing a new version with CakePHP, this implies a lot of conventions that I want to follow, that is, I'd like to keep things the cakePHP way as much as possible.
But:
There is a users table that I am trying to split into two new ones on the new version, adding fields and dividing user identification fields and usage statistics fields, I am still looking for the best way to do this easy, this is not the main question but any help will be appreciated. The table name is different to adjust to convention, and fields have changed. I still have to do some research of this.
The old site used sha1() to hash passwords and I want to know if there is any chance of keeping the records without making all the users register again.
I found some cracking tips to do it faster than brute force. Well, they say they are faster, but I have about 1000 users. Besides, I don't think it's legal nor ethical to crack my users passwords to make my work easier. So cracking seems to be out of the question.
I thought of just copying the records as they are and set a "reset password" for them, so they can just log in again with a code sent to the email they provided when registering. This is not a very bad option, but I'd like to do it only if there's no other way.
Well, is there a way of doing this?
Even if you would crack the SHA-1 hashes, you wouldn't be sure if you found the real password or only a collision. So you could not rehash these found passwords with a different hash algorithm.
It's not necessary to reset the passwords, you can just wait until the user logs in the next time.
Then you can first check for the new algorithm.
If it does not match, compare it with the old SHA-1 hash.
Should the old hash value match, then you can calculate and store the new hash, since you know the real password then.
Every password-storing-system must have the option to switch to a better hash algorithm, your problem is not a one-time migrating problem. Good password hash algorithms like BCrypt have a cost factor, from time to time you have to increase this cost factor (because of faster hardware), then you need the exact same procedure as you need for the migration.
I really recommend to switch to a slow key-derivation function like BCrypt, instead of the fast hash algorithms like SHA-1 or even SHA-256, because they are ways too fast and can be brute forced too easily (3 Giga SHA-1 values per second in 2013).
You can keep your existing passwords if you want. Just make a custom Authenticate class for AuthComponent and override relevant method to use the hashing scheme you want.
Yes, you can reset passwords or apply at your new system the same hashing algorithm as it was on previous one.
I've been studying/looking about on Google for TOO long and although I find many so-so tutorials, I'm wondering a bit about the "optional SALT" parameter in the (crypt) function within PHP. I have too many tabs open and getting nowhere so, at this point, I figured id just ask for help.
As far as the salt, I read somewhere that if you don't add it, it will be added for you but that this is not good practice. I can't seem to find the "why" it's good/not good. How should this be handled?
I've read a few things here and there about randomizing salts but others say it doesn't matter...again, confusing.
Also I'm having problems checking against the stored data as well. Obviously if I do something like
crypt("pass string here",salt here);
ill get a random string for the pass....so on a user log in, then the value of
$_POST['the entered name/pass etc '];
and checking against the db value for that users pass would always equal to false. So then I suppose that id have to rehash /salt the pass given upon user entry and then test against what's on the db?
Also, I've read throughout the net (but at this point I'm confused) that somehow the salt is stored in the db? and it doesn't have to be hidden?
I can keep going on and on, just lost honestly, I think I've read too much and not sure how to proceed. At this point, What id REALLY prefer is a GOOD link with tutorial if anyone has those resources.
You need to generate a secure random salt value when the user signs up, and store that salt in the database.
When the user logs in, fetch the salt and hash from the database, compute the hash of the password they typed using the original salt, and make sure the hash matches.
Also, don't use general-purpose hash algorithms (such as MD5 or SHA*); instead, use dedicated slow password-hashing algorithms, such as bcrypt or scrypt or PBKDFv2.
To maximize security, you never have a plaintext password in the database and leave it open to anyone who has/can get access to that database. So what you do is pick a predefined salt, take the user's desired password and encrypt it using the salt and a hash.
The salt is some extra random characters you add on to make the hashed password even more secure., you should keep track of this.
The hash then takes the salt + password and generates a random string based on it, such that you will always get that unique hash if you give it the same salt+password.
This seems like a fairly useful introduction to salting/hashing:
http://crackstation.net/hashing-security.htm
According to PHP's doc, bcrypt salt are made of
"$2a$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z"
So, if i use the crypt() function to hash my passwords, the resulting output include the first 7 chars ($2a$10$, if 10 is the cost parameter) as a part of the salt - and, according to all examples i was able to find across the internet, this complete output is written to db.
I'm wondering what's the point in storing those first characters with the rest of the salt and the encrypted data. Their meaning is fully clear to me, but i can't really understand why such informations should be written alongside the rest of the hash. Aren't they "just" informations about the algorithm and the adaptive cost of the computation? So what's the benefit in storing such application-related info? And (even if may sound childish) why disclosing them to an attacker which can eventually grab my database?
The reason is because of how crypt works. It's designed so that you can do the following
if ($hashedPassword == crypt($rawPassword, $hashedPassword)) {
//Verified
}
So by storing everything, you don't need to recreate the salt string every time...
And the point of a salt is not to be secret. In fact, it is not meant to be secret. It's meant to foil rainbow tables. remember, if they can grab your database, the chances are high they can get other things as well, so putting the salt elsewhere isn't really going to give you much.
Besides, the salt won't help much. BCrypt is designed to be CPU-Hard, which means that brute-forcing (even with knowing the salt) is impractical. That's why you have a cost parameter. So don't worry about "hiding" the salt. Just store it along side the password and you'll be fine...
Not to mention that what happens if in the future you want to tweak your algorithm? For example, let's say you want to increase the cost parameter due to better hardware being installed. If you didn't store this information with the password, all of your stored passwords would become invalid. This way, each password stored has all the information necessary to verify it. That way, you can check on valid login if the hash is the current default, and if not rehash and update the database with the new one. It prevents the issues associated with updating and improving the hashing methods...
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