Reputation: 5013
I am looking to know how I can edit my code in order to encrypt users passwords. At the moment the user fills in an HTML form which submits to customerRegister.php
which goes through a series of validations before submitting the query.
customerRegister.php
registerUser($_POST['firstName'], $_POST['lastName'], $_POST['username'], $_POST['houseNo'], $_POST['StreetName'], $_POST['town'], $_POST['postCode'], $_POST['emailAddress'], $_POST['phoneNumber'], $_POST['password'], $_POST['conPassword'],$_POST['carRegistration'],$_POST['carMake'],$_POST['carModel'],$_POST['carYear'],$_POST['carEngineSize'],$_POST['carFuel']);
function registerUser($firstName, $lastName, $username, $houseNo, $streetName, $town, $postCode, $emailAddress, $phoneNumber, $password, $conPassword, $registration, $carMake, $carModel, $carYear, $carEngineSize, $carFuel) {
$registerQuery = new UserLoginQueries();
/********************************
SERIES OF VALIDATIONS
********************************/
$registerQuery->insertUser($firstName, $lastName, $username, $houseNo, $streetName, $town, $postCode, $emailAddress, $phoneNumber, $password);
Those details are then passed to userLoginQueries.php where the query is executed.
userLoginQueries.php
public function insertUser($custFirstName, $custLastName, $username, $houseNo, $streetName, $town, $postCode, $email, $number, $pass) {
$sth = $this->conn->prepare("INSERT INTO `customer`(`CustFirstName`, `CustLastName`, `HouseNo`, `StreetName`, `Town`, `PostCode`, `EmailAddress`, `PhoneNumber`, `Username`, `Password`) VALUES (?,?,?,?,?,?,?,?,?,?)");
$sth->bindValue (1, $custFirstName);
$sth->bindValue (2, $custLastName);
$sth->bindValue (3, $houseNo);
$sth->bindValue (4, $streetName);
$sth->bindValue (5, $town);
$sth->bindValue (6, $postCode);
$sth->bindValue (7, $email);
$sth->bindValue (8, $number);
$sth->bindValue (9, $username);
$sth->bindValue (10, $pass);
$sth->execute();
}
When the user enters their login information the following query is ran:
public function queryLogin($username, $password) {
$sth = $this->conn->prepare("SELECT * FROM customer WHERE Username = ? AND Password = ? AND UserType = 'Customer'");
$sth->bindValue (1, $username);
$sth->bindValue (2, $password);
$sth->execute();
$count = $sth->rowCount();
return $count;
}
How can I modify my code so that the users password is encrypted?
Upvotes: 0
Views: 3343
Reputation: 415600
An important thing to remember here is that "encrypt" is the wrong word. The ability to encrypt implies the ability to decrypt, and that is a bad thing for passwords. You should never ever ever decrypt passwords. Instead, you need to hash a password. Hashing uses a complicated math problem to distill a text input (such as a password) into a very long number. The longer the potential number, the more secure the hash is likely to be. The important thing here is that hashes cannot be reversed. If my password is "p4$$w0rd", and the resulting hash is "12345", there is no way ever to get "p4$$w0rd" back from "12345". To authenticate users, when someone tries to log in you compute the hash of the password they used, and then compare that with the hash value you have stored. You don't store the password anywhere. Ever. Yes, this does mean you never offer an option for a user to recover a lost password; you only ever allow them to reset it.
Additionally, hashes by themselves are not good enough. It turns out that password databases themselves are compromised all the time, and hackers often already know your hash values. Hackers have devoted a lot of resources to creating ready-made tables of password inputs that will result in given hash value. So for my example five-"digit" hash, they'll have something pre-computed for every possible hash from "00001" to "99999". Their value for "12345" may not match my "p4$$w0rd", but it doesn't matter: if it produces the same hash, that's good enough. A hacker can use this to look at a compromised database and discover a valid set of credentials for every user. For this reason, you also need to salt your passwords before you hash them. When you salt a password, you modify the submitted string before hashing it. When authenticating my example password, instead of checking against "p4$$w0rd" you would first append my user account's salt, and hash the result. If a cracker knows my hash and is able to look up an input that would produce my hash in a table, it is no longer helpful to him because you will modify his input in a way that will break all pre-computed hash results. This has him back to brute-force guess every single password.
It's also important to know that not all hashing algorithms are created equal. Some hashing algorithms, such as md5, are specifically created to be fast, such that you can use them to quickly compare larger blocks of text to a know sample. These algorithms are really bad for use with passwords, because a hacker can guess many many possible passwords very quickly. You want an hashing algorithm that is very slow, so that it takes a hacker a very long time (perhaps centuries) to guess a real password, even with super-fast or specialized hardware. The best algorithms can be dynamically tuned, so that as hardware gets faster and faster over time, the algorithm gets slower and slower. Examples of these algorithms are "bcrypt" and "scrypt".
Finally, the most important lesson is to not try to build your own authentication system at all. The problem with authentication is that is easy to build something that seems to work, but is still flawed in subtle ways, such that you may find a year later that you were hacked six months ago. The system might even pass a number of well-written unit tests, but still have these subtle flaws. You always want to rely as much as possible on pre-written authentication modules available for your platform. This is also why authentication schemes that allow you log in via Facebook, Twitter, OpenID, etc are becoming more popular.
Upvotes: 2
Reputation: 3508
You should really store your password with a hashing algorithm http://en.wikipedia.org/wiki/Hash_function (one way algorithm) using salt, see http://en.wikipedia.org/wiki/Salt_(cryptography)
One of the fundamental reasons for this would be so that if your database were to be compromised, the attacker would not know what the actual password is.
A simple hashing algorithm, is sha-1. You can see how to use it here http://php.net/manual/en/function.sha1.php
Hashing using salt
The following may help: -
$sth->bindValue (2, sha1($password . "random private stuff here as salt"));
Next time you want to verify a password, just compare the entered password and your salt with the actual value and salt. This will let you know whether the password is correct without having to ever save the users password in plaintext.
Why use salt?
Well, although typically one way functions cannot be reversed, they can be brute forced. This may mean that even though you're using a hashing algorithm, some passwords may be vulnerable.
Upvotes: 2
Reputation: 5573
Please take a look at this answer: How do you use bcrypt for hashing passwords in PHP? , you would just have to call the $hash = $bcrypt->hash('password');
when registering the user and then save the hashed version of the password into the database. You can then verify the user by using $isGood = $bcrypt->verify('password', $hash);
Upvotes: 2