using sha256 as hashing and salting with user's ID - php

I'm gonna use sha256 for my site,to secure my users passwords,and as salt i was thinking of usings the users id (int auto_increment). that will be unique but not very long and hard,and public(user.php?id=1) but it just matters if its unique right?
hash('sha256', $id . $password);

Yes, it is important that the salt is unique (collissions sufficiently unlikely), but it should also have enough entropy (be random and long enough). User ids are not random and may be too short, so your best bet is to use randomly generated strings and store them in your database alongside the hash.
Suppose a user with UID 9 chooses a stupid password: password. The resulting string that will be hashed may then be 9password. You can imagine that even in this case, the full string may appear in rainbow tables (tables which contain lots and lots of hashes with their original string).
If the salt in this case would be, for example, OTAzMzYzODQzMjk5NTM1NDc1N, the string to be hashed is OTAzMzYzODQzMjk5NTM1NDc1Npassword, which is a lot more unlikely to appear in rainbow tables. Also, the input strings are a lot longer, reducing the risk of brute force attacks.

This would work but the purpose of using salt is to differentiate the hash key to strengthen the crypt algorithm. It would be much better to use a unique, random generated / time salted string for salt. Also it would be better not to include the salt and hash key in the same table.

Your salt should not be easily guessable. In one of it's more basic forms, you could simply create a salt based on the current TIMESTAMP using
date('U')
which is far more secure due to its length, uniqueness, and the fact that you store it in the DB and don't make it publicly available. You would then utilize it in such a manner:
$hash = date('U');
$pass = hash('sha256', $hash . $password);
and as far as checking passwords on login:
// return query object based on matching email/username
if ($userobj->pass === hash('sha256', $userobj->salt .$_POST['pass'])) {
// correct pass
}

I don't think that is a good choice: I would use a more random salt saving it into the user record.
Maybe saving in the password field this string: sha256($password . $randomSalt) . '$' . $randomSalt
This way you can then retrieve the salt to check the passoword on login.
(Anyway you can also use another field for the salt alone)

Related

Does reapplyingsha1() to passwords over and over aagain help at all?

Since the PHP sha1() can be broken quite easily by comparing against a long list of hashes - would this be any better (basically - applying sha1() over and over again to try and make brute forcing impractical by slowing the hashing process down):
<?php
$iterations = 100000;
$pass = 'hyugf67rf76dt564d5r76';
$salt = '6t6755636459679guytfugiuhbguiygfytcdtresr5tdt5yfuybiugbuyfr56d45esertdcftyuuguy';
$hash = '';
for ($i=0; $i<$iterations;$i++) {
$hash = sha1($hash . $pass . $salt);
}
echo $salt . $hash;
?>
Instead of applying the sha1 over again and again , why not implement crypt() once with a stronger - salt ?
If you have PHP 5.5 +, you could simply go for password_hash()
A userland implementation of password_hash() is also available here
HINT : You could combine the examples #4 and #3 of the password_hash()documentation link above to creater a stronger hash.
or use phpass
The preferred (most secure) hashing method supported by phpass is the
OpenBSD-style Blowfish-based bcrypt, also supported with our public
domain crypt_blowfish package (for C applications), and known in PHP
as CRYPT_BLOWFISH, with a fallback to BSDI-style extended DES-based
hashes, known in PHP as CRYPT_EXT_DES, and a last resort fallback to
MD5-based salted and variable iteration count password hashes
implemented in phpass itself (also referred to as portable hashes).
A better way to approach the problem, is by using a hashing algorithm that has this cost-intensity built-in, instead of using a custom function. If the resulting hash is not truly random, this could be a security problem.
That doesn't answer your question though, so I'll try to do that now.
Cost-intensity
If applied correctly, algorithms that are more cost-intensive make it more cost-intensive for an attacker to crack all passwords from a database. If applied incorrectly though, most of this cost-intensity can be bypassed. This is why I recommend using an algorithm that is designed to be cost-intensive, rather than trying to create something yourself.
Salts
A database-wide salt only protects you from rainbow tables without a salt. When an attacker obtains your database with passwords, and knows the salt, they can make their own rainbow table with your salt, and crack every password in the database with this rainbow table. Users with the same password have the same hash in the database.
A per-account salt (a salt that is different for each account), an attacker has to crack each password individually. Users with the same password have a different hash in the database. Cracking passwords is much more costly now.
Iteration
What you should be wary of when reapplying, is that the attacker should not be able to create a lookup table for part of this iteration. In other words: The iteration should contain something that is different for every user, and even better, different for every password tried for an user. Since you re-use the password in the algorithm, this should be no problem.*
A little change to the algorithm could however allow an attacker to bypass most of the iteration. In the following code, the attacker could create a lookup table that translates a hash to a hash with sha1 applied 99.999. In fact, such a table can be created by applying it just once on every hash, then using that lookup table multiple times. Instead of needing to apply sha1 100.000 times for every password, this now has been reduced to creating a lookup table, applying sha1 exactly once for every password, and looking up a hash in a lookup table once for every password. Even with a per-user salt, this would make no difference to the lookup table.
If you would use a per-user salt and change the line with //here to sha1($hash . $salt), the attacker has to create such a table for every unique salt in the database. This is slightly more work, but still much less than the work an attacker has to do when he has to calculate every hash for every password they try out.
<?php
#Bad code below
$iterations = 100000;
$pass = 'hyugf67rf76dt564d5r76';
$salt = '6t6755636459679guytfugiuhbguiygfytcdtresr5tdt5yfuybiugbuyfr56d45esertdcftyuuguy';
$hash = sha1($hash . $pass . $salt);
for ($i=0; $i<$iterations;$i++) {
$hash = sha1($hash); //Here
}
echo $salt . $hash;
?>
* I am by no means a security expert. I am a student with some knowledge about algorithms, and some knowledge about security, but the fact I don't see a problem doesn't mean there isn't a problem.

How to check if the user entered the password that matches the whirlpool hash?

I just recently began looking into password encryption.
My current code looks like this :
<?php
define('salt','7hPqMO(m=F+!!L6(#Yhp-CdF, &Q}+cIrA;c#wcP(E--V<qRmq!v*aSnM;H=4cD0');
$password = "CatsRsoCool47";
$myHash = hash( 'whirlpool',salt.$password );
echo $myHash;
?>
How would I check if the user inputed the correct password? I assume there is some sort of built in function that takes the parameters of the salt,hash and the encryption method and returns a boolean.
Also, what is the safest way of generating a salt? The current salt I have is static and the same for every user. Should I do something like
$salt = Time()+'7hPqMO(m=F+!!L6(#Yhp-CdF, &Q}+cIrA;c#wcP(E--V<qRmq!v*aSnM;H';
If it was done like so, wouldn't I have to store the timestamp in the database per user. Isn't that a security flaw?
I am lost.... Please suggest the best way to hash and check passwords. A script would be nice to look at :) This question might also be a possible duplicate, if so I'm very sorry
Basically, when a password comes in, whatever you did to store the password, you use the same thing applied to the incoming password.
You can then check that the two salt+hash values are the same.
It's as simple as that - do the same thing to the two passwords and you should get the same result.
You're right to be worried about using the same salt every time. What you really want to do it to use a different salt each time. You can then store the salt alongside the password. It sounds counter-intuitive, but this is perfectly OK. Having the salt doesn't allow you to reverse the hash as the process isn't reversible anyway.
Then, when you want to check a password, you look up the user, get their salt, use it to apply the hash and then check what you end up with against their stored hash.
For example (using a constant salt), you might have something like:
<?php
define('salt','7hPqMO(m=F+!!L6(#Yhp-CdF, &Q}+cIrA;c#wcP(E--V<qRmq!v*aSnM;H=4cD0');
$incomingPassword = $_POST['password'];
$storedHash = getStoredHash( $_POST['username'] );
$incomingHash = hash( 'whirlpool',salt.$incomingPassword );
if ( $incomingHash == $storedHash ) {
echo('Passwords match!');
}
?>
Hopefully it's easy to see how you might use this technique with a moving salt.
Note - this is not encryption - the whole point is that the method is one way. You generate something that cannot be used to retrieve the actual password. Encryption implies the process is reversible.
Attacks on hashed passwords are done by what's called a 'rainbow table'.
The attacker builds a table of possible password alongside their corresponding hashes using the same technique that you use. This table is then compared against your stored passwords. When there's a match the attacker can then infer the password that was stored for that row.
Having a single salt makes this easier as the technique is identical for every password. If you use a different salt per row then the technique has a random factor meaning the attacker needs a MUCH bigger rainbow table to attack you with - essentially a full sized table per row.

Salting passwords PHP, MySQL

Is the following a good way to salt passwords?
hash('sha256', $_POST['password'], $_POST['email'])
I am using the user email as a salt. Some people do not use emails, some others say to use a random number.
Even if I use a random number then I will still need to store it on my MySQL table, so the salt will still be known anyway, and with the added benefit of using emails is that the possibility of rainbow tables is greatly decreased, even if I was to use a 16-bit integer?
The idea behind a salt is to prevent a hacker from using a rainbow table. For instance, if the hacker is able to compromise your database and figure out what the hashed password is he can't easily reverse engineer the hash to find a value that would generate the same hash.
However, there exist tables of already hashed words called rainbow tables. Some people have already gone through the trouble of calculating the hash of every word in the dictionary and other common passwords. If the hacker has one of these tables, plus the hashed password from your database, it makes it very easy to figure out what the password is.
However, a salt changes all that because now, instead of hashing the password, you are hashing the password plus some random value which means that the rainbow table is now useless. It does not matter if the hacker can compromise the salt.
It is perfectly fine to save the salt in clear text. You want to use something that is not uniform across all users either because, again, that defeats the purpose. I personally like to use the timestamp the account was created.
Does that make sense?
What happens if a user changes his email address? You won't be able to verify his/her password anymore because the salt value will be gone.
You shouldn't use anything as a salt that is likely to change over time. Generate a random salt (long enough to defeat rainbow tables) and use it together with the password to generate the hash.
Right now the best possible solution to use in PHP for password hashing is to use the bcrypt (blowfish) implementation. Why? There are several reasons:
variable 'work' parameter
built-in salt
Keep in mind that if you are not running php 5.3, then crypt_blowfish may not be available on your system.
Work Parameter
Blowfish/crypt is already has an expensive setup time but by setting the work factor you can increase the amount of time it takes to calculate a hash. In addition, you could easily change that work factor in the future as computers get faster and are able to compute hashes more easily. This makes the particular hashing method scale.
Built-in Salt
For me this is just laziness but I like that the salt & pass are stored together.
Implementation
To use blowfish you'd create a hash as follows
// salts must be 22 characters
$salt = "ejv8f0w34903mfsklviwos";
// work factor: 04-31 (string), each increase doubles the processing time.
// 12 takes my current home computer about .3 sec to hash a short string
$work = '12';
// $2a$ tells php to use blowfish
// you end up with a string like '$2a$12$mysalthere22charslong'
$options = '$2a$' . $work . '$' . $salt;
$hashedPass = crypt($plaintext, $options);
To verify a hashed password is simplicity:
if(crypt($user_input, $stored_password) == $stored_password) { echo "valid!"; }
Now, if at any given time you want to increase the work factor you could take the submitted pass after a successfull login, and rehash and save it. Because the work factor is saved along with the salt & password, the change is transparent to the rest of the system.
Edit
There seems to be some confusion in the comments about blowfish being a two way encryption cypher. It is not implemented as such in crypt. bcrypt is an adaptive password hashing algorithm which uses the Blowfish keying schedule, not a symmetric encryption algorithm.
you can read all about it here: http://www.usenix.org/events/usenix99/provos.html
or you can read even more about using bcrypt (the hashing implementation of blowfish) here: http://codahale.com/how-to-safely-store-a-password/
i suggest using iteration such as below. The crypt could be replaced with md5 or any other hashing algorithm. the 10 could be any number.
$pass=mysql_real_escape_string($_POST['pass']);
$iterations = 10;
$hash = crypt($pass,$salt);
for ($i = 0; $i < $iterations; ++$i)
{
$password = crypt($hash . $pass,$salt);
}
In addition, you could add any other variable. I hope this solve the problem
You could use this:
$salt='whatever';
$a=hash('sha256', $_POST['password'], $salt);
$b=hash('sha256', $_POST['email'], $salt);
$hash=$a.'-'.$b;
When the user changes the email, just do:
$old_a=substr($old_hash,0,strpos($old_hash,'-'));
$new_b=hash('sha256', $_POST['email'], $salt);
$new_hash=$old_a.'-'.$new_b;

What encryption method is used on these passwords?

I am working on a program that needs to know what is used to encrypt passwords in the application Tigerpaw 11. Tigerpaw 11 uses SQL so I can see the encrypted password I am just not sure what particular encryption method is used.
I changed one of the users passwords several times so I had some examples for you guys.
For what it helps this is what I know about the application:
- Ties to MS SQL for all data
- Seems to be written in a .NET language
Samples:
123456, 6df7a625c514577b8ce73af649e3c179
MyPassword, ec46ca799923b1a6ffab6b5cb75d059a
CrackIt, b4df19b23f1882e4d0a42e2451443628
They seem to have some kind of hash value based on user. For this instance it could be "Tim Way" or 50 amongst other fields.
The end result is I want to be able to do user authentication in PHP against this password.
They are probably not encrypted but hashed, the fact that the 'encrypted passwords' are all the same length should have given you a clue. Common hashing functions are MD5 or SHA1.
The passwords are not encrypted, but hashed. Your hashes seem to be hashed with the MD5 hashing function. Probably a secret salt is used to make guessing common passwords harder.
It appears that they are using salt in there hash.
Salt is a somewhat secret term used change the hash value. I doubt they would want to tell you the salt.
you can see the results from many popular hashing algos here
http://www.insidepro.com/hashes.php?lang=eng
It's probably a MD5 hash of the password and user name (and/or user ID, if that exists). Also check if there is something else related to the row in the user database table that might also influence the hash. For example, when setting the same password to the same user produces different hashes then there probably is something like a SALT value (a random value or string that changes with each password update).
Given these values you have to guess how they are being combined. If you're unlucky, then they might even use separators and such.
I'd try with
md5($username . $password);
md5($userID . $password); // assuming there is a numeric user ID too
md5($password . $username);
md5($password . ":" . $username); // separator example
md5($username . $password . $salt) // if there is any
Any any other combination that comes to your mind. Good luck.
It looks like md5 hash salted with username and secret key (sha1 is 40 chars long).
This is reviving an old thread however as of version 14 encryptions have been converted to AES256
I know this applies to credit card details, Not sure if it applies to passwords, They are likely just a hash as per previous answers.

Salting Algorithm Strength

What are the advantages / disadvantages of those 3 methods to create a salt?
$salt = md5($password);
$salt = sha1(md5($password));
$salt = generate_random_number();
Computing hash:
$hash = sha1($salt + $password);
Salts
To answer this question it's important to know for what salts are.
Salts are designed against attacks with pre-calculated tables. For example rainbow tables. Rainbow tables are huge tables with all possible password variations up to a certain length. (Using a clever memory/time tradeoff.)
If the attacker only wants to crack a single password, they don't offer an advantage.
The statement above is not true if
The database doesn't use salts. Then a common rainbow table can be used.
The salt is too short. If the salt is too short, it has the same effect as just having a longer password.
It's a common salt like salt. There are for sure already some rainbow tables with that salt included.
Attackers using rainbow tables usually want to crack as many accounts as possible.
Which of your methods is most secure?
All of your methods except the third are insecure. This is because using any of the other methods allows the attacker to calculate a rainbow-table for your whole database.
Because the salt is dependent on the password. Don't make it dependent on the username either, this would still allow an attacker to create a rainbow table for the 100 most common usernames.
Keep in mind
Use only a cryptographically secure random generator to calculate your salts.
Don't use MD5. It's already considered broken, use at least SHA1.
The first two methods are worthless. The whole point of salting is that the same password does not always result in the same encrypted/hashed string.
If you make the "salt" dependent on just the password, the same password will always result in the same hash. So basically the result is the same as if you'd use a slightly different hash function without any salt.
With the third method two users with the same password will usually get a different salt and the hashed version of the password will look different for both users. It will be hard to tell by the hashes that they both have the same password.
Well strictly speaking you only have one salting method, where you calculate the hash. The first three lines are different ways of generating a salt.
So a salt is there to stop precomputed lookup tables from discovering passwords. It should be a fixed value stored someone that is, preferably, unique to the plain text being hashed.
The most secure would be to use a cryptographically secure random number generator to produce a salt which is then stored along side the password.
If you created a salt which was an MD5 of the password then it would have to stored alongside the hashed and salted password value, which means you have an unsalted hash which is vulnerable to precomputed lookup tables, unless you plan to calculate it every time which is a small performance hit. By taking a SHA hash of an MD5 hash you're reducing the possibility of the plain text values, as there's a finite number of MD5 hash values as they are fixed length. This would mean that a rainbow table lookup might have a greater chance of success than a truly random salt.
So use the random salt please.
A useful way to think of rainbow tables is that they can be built for any one-way (or "trapdoor") function that only has one input. That is, if you use the same function, F, for all your passwords: hash = F(password). F could be MD5 or SHA1 or whatever.
Now lets look at salts. You use a salted function G, hash = G(salt, password). If all passwords in your database use the same salt, you can construct a function G, where G(password) = F("your salt", password), so there is a single input function, and thus you can build a rainbow table.
What if the salt depends on the password? Say the salt = I(password), we can build J(password) = G(I(password), password), a single input function, so rainbow tables can be built.
So, each password needs to have its own salt. This means that in the time it would take an attacker to crack all of your passwords, they can only crack one.

Categories