Hash Passwords php - php

I have a very basic logon system, that authenticates users by the means of a user table in a mysql database with php.
can someone explain what the point of hashing passwords it, how to do it with php, and what is actually stored in the database.
Thanks

can someone explain what the point of
hashing passwords it,
The point of hashing passwords is for security purposes. If inserted as plain text, anyone that gets into your database will now have all of your users passwords. Another huge problem that stems with this is that it more than likely compromises the user everywhere, not just your site, as most people tend to use the same password everywhere.
how to do it
with php, and what is actually stored
in the database.
To use it in PHP you simply take a string, in this example $password = 'password'; and use the command sha1();. This will return something like d0be2dc421be4fcd0172e5afceea3970e2f3d940. It is also good practice to 'salt' passwords with your php script, so that the PHP script login script is required to successfully log in. Example:
<?php
$salt1 = '2348SDasdf!^*__';
$salt2 = '_a35j#*#(lsdf_';
$password = sha1($salt1.$_POST['password'].$salt2); // d0be2dc421be4fcd0172e5afceea3970e2f3d940
?>
Then insert $password into your database. Upon logging in, you would need to salt the password given run it through sha1 in order for it to match the password in the database. You insert it into the database just like any other string, just make sure you have sufficient length granted to the column you're attempting to insert too.

Say someone breaks into your system (or finds a loophole in your sql queries) then you don't want them to know all passwords.
So you hash them before storing them. So you can check if the password is ok, but not deduce the password from the hash.
Unless you use a weak hash. If you would only sha1($password) then you will find putting the hash of often-used passwords into google gives the password in under 0.1 sec.* (but otherwise you could also find rainbow tables for all kinds of hashes)
So you want to add a "salt", that means, you generate some garbage value:
$salt = rand().rand().rand();
and then store
$hash = $salt."-".sha1($salt.$password);
on checking, you know the salt and you can check if the password is right, but knowing the hash and salt makes it still hard to recover the password. (unless you have a rainbow table which includes the salt, of course)
* this needs some explanation: I once took a large user table and found some hashes to appear multiple times. I googled the most-occurring one and it reversed to computer

A hash is a "one-way function". You feed in a password and get an approximately unique output that cannot be (computationally feasibly) converted back into the real password. Depending on the hash, it will look different. For instance, with sha1 (http://php.net/manual/en/function.sha1.php) you will always get a string 20 bytes long.
The benefit is that the real password is never stored in plaintext. To verify the user's password, you just compute the hash on the supposed password and compare it to the stored hash. If somebody gets a hold of your password database, they still don't have the actual passwords.

Noone has said why yet, so let me: most users are idiots and use the same password everywhere. You don't want a hacker to break into your system, grab the passwords then go and hack your users accounts everywhere else.

Related

How to get salt from a password and use it to validate user? [duplicate]

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.

What is the point of encrypting passwords in a database?

Could someone please confirm the following for me:
Is the point of encrypting passwords when saving them into a database that if the database is hacked into then the hacker won't be able to know the actual passwords, unless s/he has the algorithm and salt etc to decrypt it, and therefore won't be able to compromise this or other accounts using the same password?
But my main query is: presumably the password is encrypted in, for example, the PHP script that saves the password into the database, and therefore the algorithm to decrypt the password is clear in that script. So is it correct that if the hacker hacked into the server or content management system for the website s/he would be able to access that script and decrypt the passwords?
So essentially the encryption is only as relevant as your login information to your online CMS or server is strong?
Thanks in advance!
Your passwords shouldn't be encrypted in the database.
What is commonly done is taking a hash of the passwords, and storing that in the database. A hash is a one-way function. It isn't possible to reverse it and get a result. To check to see if a password is correct, the test password (what the user enters) is re-hashed with the salt to see if it matches the has from before.
This way, should someone obtain a copy of the database, they only know the hashes, which take an incredibly long time to find a collision (match) for. Adding a unique salt for each password ensures that users with the same passwords have different hashes, meaning the work to find hash collisions has to happen for each password (very slow).
You're missing the point. You do not store encrypted passwords in a database, you store password hashes in the database.
You do not want to decrypt the password, you want to compare the stored hash with a calculated hash!
Passwords aren't actually encrypted. They're actually hashed via a one-way hashing algorithm. This means that "theoretically", an attacker shouldn't be able to reverse the hash. Problem is: A lot of beginner web developers will use hashing algorithms that are fast. This means that the usage of lookup tables becomes an issue, where a script can be used to hash a whole bunch of dictionary words and then compare them against the hashed password from the DB.

Actual password visualisation in SQL table when using sha256

I am training to secure the login process.
I have used sha 256 in the sign_up.php:
$username= check_input($_POST['username']);
$password= check_input($_POST['password']);
//the password is encrypted in sha256
$secure_sign_up_password = hash('sha256', $password);
and then of course in my users table in my SQL database, I can read:
in the column 'login' the actual typed login
example: if somebody type 'michael', I will see 'Michael' in the SQL database
in the column 'password' the actual typed login
example: if somebody type 'fruit', I will see the hashed value like 'e8bfab56c53980cd014206c8da2f8c9b9708eaacc61' in the SQL database
My question is simple but maybe a bit naive (I'm a newbie): I thought that I could still be able to read the actual password somewhere in my database and that hashing was only made to protect the password from getting intercepted and read while it was being sent. I never know, somebody might ask me to send him his real password. But the only thing I can see is the 'hashed' one in the password column.
Is it made to be like this?
Is it possible to visualize also the real password?
If you would be able to "decode" those passwords, it wouldn't be a very safe system. Once someone gained access to your database - they would be able to gain access to every ones passwords without them knowing...
If you have ever forgotten a password for a site (and we all have - don't deny it!), you'll recall that they usually* don't simply send you your password (in plain text) as a reminder to your email - they'll give you the opportunity to reset it. This way (verifying usually through your email/phone number) they'll know that you are indeed the person who opened the account.
* If they send you your password in plain text that probably means they are storing it like that or in some other easily decrypted form. This site is most likely not as secure as they would like to think...
If you are interested in leaving yourself a "backdoor" of sorts to be able to access any of your users accounts, what you might think of doing is having a special login form from inside your administrator account, that allows you to use the encoded password to log in. That means that you simply leave out the hash('sha256', $password) and pass the $password already encoded (which you extract from your database). It's a bit hacky, and if you already have an administrator account then there wouldn't be much use to be able to log in as a different user because you are already all powerful!
This is by design. Nobody should know what my password is, except for me. Even you as a (insert fancy title here) should not know my password. If I forget it, that's my problem, but your site should offer me a way to reset it. Then when I reset, your site should store the hash once again. The plain-text password should never be stored anywhere.
Never never never hold password in open format in database. If someone find exploit in system, he will be able to make any sql query and get users passwords. And hacker will be able to login into system as user, because he knows username and password
If user want restore password, make functionality for regenerating password. Never store password in plain text.
SHA256 is hash function. Mathematically it means - data can be "hashed" only in one way. I mean, that from hash you cannot restore data. You can read this http://en.wikipedia.org/wiki/Hash_function about hash functions and this about http://en.wikipedia.org/wiki/Sha256 sha256
Result: If someone crack you database and get username and password, he is unable to login into system. Because hacker have only hash data and can't get exactly password for login.
As i mentioned before, hash function can be "hash" data only in one way. But some hackers build VERY big data massive for some predefined algorithms. I mean, that they build hash tables for passwords. Such hash tables looks something like this:
password hash
------------------
a some_hash1
b some_hash2
... .....
qwerty some_hash3
some_data some_hash3 -- yes, data can have collisions. See wiki about hash functions
And if hacker hacked you database and have such table, he able to restore password. For example, hacker get for admin user hash "some_hash3", then hacker search such hash in hash table, find that hash "some_hash3" have password "qwerty" and "some_data" and hacker will try to login with such passwords.
Result: Use salt. For nowadays hackers have such tables for 6 symbols passwords. But you can "suck" them in very simple technic: When you store password in database, add to password some value (salt) and get from such value hash:
// somewhere in code, where creating/updating users password
$password = hash('sha256', $salt.$password);
and when you will check password, use the same logic
Thanks
sha256 hashes and other hashes are one way. See http://en.wikipedia.org/wiki/Cryptographic_hash_function. If you want to be able to decrypt what you write in the password fields in your database, you might want to use another approach.
Instead of creating a hash, you could encrypt with a key, that you do not share with your users. Look at http://www.php.net/manual/en/book.mcrypt.php. The key would be part of your code though, as it's symmetric encryption.
To do it really safe, try real PKI encryption (encrypt with a public key, decrypt with a private one). Look at php.net/manual/en/function.gnupg-encrypt.php or php.net/manual/en/book.openssl.php.
But as other here have said, such things are reasonably NOT done ;)

Inserting passwords to database, any difference with a regular text field?

I'm making a registration form, my only doubt is how to handle passwords (how to insert them into MySQL database). I don't have the slightest idea on how to do it, what type of column must Passwords be, whether I must encrypt them somehow, etc. Could you provide a basic example with explanation so that I manage to do it?
You don't want to store the password as-is in plaintext. You don't even want to be able to know what the password is. Therefore, you store a hash of the password in your database. When the user wants to log in, you hash the password he's trying to login with, then compare that to the hash in the database. Any serious password storage system furthermore salts the hash to prevent rainbow table attacks against the password (google that). Since this is a rather complex topic and you apparently have no experience with it at all, I recommend you use phpass to hash and salt your passwords without worrying about the implementation details. The phpass site also has some good introductory articles about the topic. Here's another one that keeps it really simple.
As for the database, that'll just be a normal VARCHAR field long enough to hold the hash.
Read this: http://codahale.com/how-to-safely-store-a-password/
Then do this: http://www.openwall.com/phpass/
You should not store password, password hash only.
Database type should be choose after you will choose hasfunction.
For md5/sha512 it will be char(32) if you will keep hex representation
Query is something like this:
"INSERT INTO users SET otherFields,pass_hash='".hashFunc($_POST['password']."';
where hashFunc generates hash ex
function hashFunc($pass){
$salt='something';
md5($salt . $pass);
}
The only way to safely secure a password is using a Moore's Law-defeating hash function. Use bcrypt!
One of the ways it can be done is by using md5. You convert the password to md5 and put it in the database (md5 encryption is one-way) when the user logs in again you convert the filled in password again and check if the converted password is somewhere to be found in your database (in combination with a username usually).
EDIT
You can make a string into an md5 string with this:
$converted_pass = md5($unconverted_pass);
However you will need to add a so called salt-key to the password before you encrypt it with md5. This is a set of letters/numbers etc. If you do this every time you will have the same result but it will be quite safe :)

Password verification; Is this way of doing it safe?

I have a classifieds website, where everybody may put ads of their products.
For each classified, the user has to enter a password (so that they can delete the classified whenever they wish).
So basically, when somebody wants to delete a classified, they click on the classified, click on the delete button, and enter the pass.
I use MySql as a database.
I use this code basically:
if ($pass==$row['poster_password'])
where row[poster_password] is fetched from MySql...
What do you think?
Thanks
See this: Secure hash and salt for PHP passwords
Hash their password (maybe with some salt) on the way into the database. Store their hashed password in the database (NOT their actual password). Then fetch their hashed password from the database and hash their input password and compare the hashed passwords.
Some lame pseudo code:
password_hash = hash(password_cleartext)
# store password_hash in database
Later:
input_password_hash = hash(input_password_cleartext)
fetched_password_hash_from_db = fetch(db, password_hash)
if (input_password_hash == fetched_password_hash_from_db) {
... authenticated ...
}
For a start with php, try: http://php.net/manual/en/function.sha1.php
Your code looks safe, but your design may need some work.
SQL Injection
The dangerous part of the code is in storing anything in the database, or showing anything to the users, that is collected from the user. So, the part you have to be careful with occurs prior to your example. Ensure that you're validating, filtering, and escaping any data that you collect from the user, including the password and the ad information.
Encryption
The advantage of storing the password in the database is that you can let the user retrieve the password via email or some other means if they lose it.
However, if you do store passwords, you should store them encrypted, using a secret key, so that if someone is able to direct read access to your database, they can't read all the passwords in plain text. Still, you're going to have to store the secret key somewhere, and if someone gets your secret key and has access to your database, they will have access to all of the passwords.
Hash Values (recommended)
It's best practice and more secure to only store one way hash values (SHA1 or SHA256) of the passwords in the database instead of the actual passwords. This way, you cannot retrieve the password. Hash values are intentionally one way by throwing away some of the data.
Instead of retrieving the original password, you hash the password that the user enters and compare the hash value against the stored hash value to see if it matches. If the user loses the password in this case, instead of emailing the password to the user, you email the user a new, randomly generated password.
Storing only the hash value protects your data even further, since even if the user has read access to your database, the hash values offer no advantage, and there is no secret key that will unlock all of your hash values.
When you hash the passwords, be sure to use a random salt value and store the salt to protect your list of hashes against rainbow attacks.
Summary
Sometimes you don't get to choose the password. Sometimes the password comes from another system, so you don't always have a choice, and sometimes your superiors (maybe even the users) will demand that they be able to retrieve passwords, however, when possible, you should choose the more secure option.
Note that all of this encryption and hash value business only partially protects your server against people who are able to obtain read only access to your data. Sometimes, getting your data is enough of a prize, so if the user can read the password hash, can they read your credit card numbers?
You need to protect your database. Do you have a secure password on your database system? Do you only allow local access to your data? Have you created a database user with least privileges to use in your application? Are you properly protecting yourself from SQL injection and scripting attacks?
If someone has read and write access to your data, the whole password business becomes moot.
Don't store the actual password in the database. Instead store a checksum (MD5, SHA1, etc). When you want to compare, perform a checksum of the value the user submits and compare the checksums.
That way you never have the actual password in memory.
Best practice is to keep a salted sha1 hash in the database:
if (sha1($pass.$row['poster_salt'])==$row['poster_password'])
(poster_salt is a random string generated and saved when the user chooses the password.)
That way if an attacker gets access to your database, they still won't get the passwords of the users (which are probably used elsewhere too - most people don't bother to choose different passwords for different sites).
Also, you should use secure (HTTPS) connection. And require sufficiently strong passwords.
(At least if you want good security, which might be an overkill in the case of a simple ad listing).
I would encrypt the password before storing it, then decrypt when retrieving it so you can check it against what the user entered in plaintext (per your example code above).
Also, protect yourself against any SQL injections, or someone could see all the passwords (and other data) in your database.
This implies the passwords are placed into your passwords unencrypted. If this is the case you should be using some sort of encryption when entering the passwords. One way of doing this is the MD5 function which hashes the password.
When doing the insert you would do
Insert into table(email, password, whatever) values('$email', md5($password), whatever)
And when comparing you would do
if (md5($pass) == $row['password'])
You should hash the password somehow and store and compare using the hashed version. See this link for more details:
http://phpsec.org/articles/2005/password-hashing.html
my suggestion is the following
the users table have two columns, one called "password" and the other "salt"
$password = 'youruserpassword in plain text';
$salt = bin2hex(openssl_random_pseudo_bytes(32));
$passtostore = hash_hmac('sha384', $password, $salt);
insert into users(password, salt) values($passtostore, $salt);
Then to verify if the user has entered the correct password...
retrive both password and salt from the database and
if(hash_hmac('sha384',$userpass, $row['salt']) === $row['password']) {
// is valid
}

Categories