I have question about valid hashing passwords:
login.php
$login = $_POST['login'];
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);
if(!empty($login) && !empty($password) && password_verify(??){
I want to make secure login and I know that I have to verify the inputted password with existing hash (stored in database?). Also I know that bcrypt everytime makes new hash (because of different salt size etc).
The problem is that I don't know how to put this hash into database because I don't want to register new users, I have static list of users (exactly two: admin and user).
I tried manually copy/paste hash but it wouldn't work as I mentioned earlier that every time I run script new hash is created.
Can anyone help me how to put bcrypt hash in database (only once) so I can only check if inputted password is same as the one in database?
Do I need extra variables to store this hash?
EDIT:
login.php
<?php
session_start();
include("log.php");
include("pdo.php");
$login = $_POST['login'];
$password = $_POST['password'];
$adminHash = '$2y$10$lxPRtzzPDUZuPlodhU4QquP.IBrGpkjMNplpNgN9S1fEKd64tJ5vm';
$userHash = '$2y$10$Klt345wT66vA.4OAN5PEUeFqvhPQJ4Ua/A4Ylpc1ZcnJZv/hafgSu';
if(!empty($login) && !empty($password) && (password_verify($password, $adminHash) || password_verify($password, $userHash))){
$query = $pdo->prepare('SELECT * FROM xx WHERE login = ? AND admin = ?');
$query->execute(array( $login, 1));
$result = $query->fetchAll();
if(!empty($result)) {
$_SESSION['logged_admin'] = 1;
}
else {
$query->execute(array( $login, 0));
$result = $query->fetchAll();
if(!empty($result)) {
$_SESSION['logged_user'] = 1;
}
else {
$_SESSION['logged_error'] = 1;
}
}
}
else $_SESSION['logged_error'] = 1;
header("Location:index.php");
?>
it seems to be working but i dont know if it's best/safest solution.
With more passwords it will be too complicated i guess, still looking for best option!
What if i need more users? now every user have same hash and it's dangerous i get it, how to make it safe? generate hash for every user and make array or hashes?
You fetch first the one that has password_hash() from your database, and then compare it with password_verify($password, $storedpassword) like this : link
Related
my login activity cannot read encrypted Password i tried without encrypted password and it works and im not sure if the error from php or activity itself of how to decryption password
im Using PASSWORD_BCRYPT
<?php
include "conn.php";
$Email = $_POST['Email'];
$Password = $_POST['Password'];
$sql_login = "SELECT * FROM users WHERE Email = :EMAIL and Password =:PASSWORD";
$stmt = $PDO->prepare($sql_login);
$stmt->bindParam(':EMAIL', $Email);
$stmt->bindParam(':PASSWORD', $Password);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$returnApp = array('LOGIN' => 'SUCCESS');
echo json_encode($returnApp);
}else{
$returnApp = array( 'LOGIN' => 'FAILED');
echo json_encode($returnApp);
}
?>
To correctly use hashing of a password in PHP, use the password_hash and password_verify combination.
When a user signs up, you get his password, hash it and store it in the database:
$hash = password_hash($_POST['newpassword'], PASSWORD_DEFAULT);
// store $hash in database column "password"
When this user wants to login, you check against the hash:
// fetch hash from database, store it in $stored_hash
$logged_in = password_verify($_POST['password'], $stored_hash);
if ($logged_in === TRUE) {
echo "Welcome!";
} else {
echo "Username or password incorrect.";
}
Final notes:
Use PASSWORD_DEFAULT and make sure your database can store the result (also in the future). Hashing algorithms happen to get cracked once in a while.
You could use another provider like Google or Facebook to handle your authentication. This does have its drawbacks as well though.
I'm looking for a simple (or as simple as possible) yet secure method for hashing and salting a users password when submitting it to the database and then retrieving from the database. Having spent the past 3 hours researching, there are literally hundreds of different methods that each person will say is the best method.
I'm looking for a relatively simple method that will also keep users accounts secure. Obviously the term secure can be interpreted differently, but i just want it, at the very least, be very difficult for a would-be hacker (or whatever you'd call these saddo's) to gain access to a users account.
I appreciate that i should have at least tried a few things, but they all seem so convoluted and overly secure for my purpose.
I tried using password_hash() but it appears i'm running an earlier PHP version than 5.5. I understand there are issues with the code below, but it's simply a starting point for a person project i'm working on in order to better learn PHP.
Current registration form
$username = $_POST['username'];
$password = $_POST['password'];
try {
$result = $db->prepare("INSERT INTO
user_info
SET
username = :user,
pass = :pass
");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $password);
$result->execute();
}
catch (Exception $e) {
echo "Could not create username";
}
if (isset($_POST['submit'])) {
foreach ($_POST as $field) {
if (empty($field)) {
$fail = true;
}
else {
$continue = false;
}
}
if ($field == $fail) {
echo "You must enter a username and/or password";
}
else {
echo "Your account has been successfully created.";
}
}
The login logic
$username = $_POST['username'];
$password = $_POST['password'];
try {
$result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $password);
$result->execute();
$rows = $result->fetch(PDO::FETCH_NUM);
}
catch (Exception $e) {
echo "Could not retrieve data from database";
exit();
}
if ($password = $rows) {
session_start();
$_SESSION['username'] = $_POST['username'];
$_SESSION['loggedin'] = true;
include("inc/redirect.php");
} else {
if (isset($_POST['login'])) {
echo "Username or password incorrect (passwords are case sensitive)";
}
}
Use sha1 function http://www.php.net/manual/en/function.sha1.php
It's really simple. Pass the password in input parameter then save it in the database.
When you want to check if password is correct you just have to compare the sha1(password) with the stored value.
Example :
$passwordEncrypted = sha1($password)
save $passwordEncrypted in your database
When the user want to login :
check this condition :
if (sha1($password) ==$passwordEncrypted )
Here is the complete code :
$username = $_POST['username'];
$password = $_POST['password'];
$passwordEncrypted = sha1($password)
try {
$result = $db->prepare("INSERT INTO
user_info
SET
username = :user,
pass = :pass
");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $passwordEncrypted);
$result->execute();
}
catch (Exception $e) {
echo "Could not create username";
}
if (isset($_POST['submit'])) {
foreach ($_POST as $field) {
if (empty($field)) {
$fail = true;
}
else {
$continue = false;
}
}
if ($field == $fail) {
echo "You must enter a username and/or password";
}
else {
echo "Your account has been successfully created.";
}
}
With password_hash() you are on the right track. For PHP versions 5.3.7 - 5.5 you can use the compatibility pack, later when you switch to a newer PHP version, you can simply remove this php file from your project and the code will still run.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
Even for lower PHP versions than 5.3.7 you can use the compatibility pack. You only have to edit line 55 and change the algorithm from sprintf("$2y$%02d$", $cost); to sprintf("$2a$%02d$", $cost);. This is of course not optimal, but it is the best you can do for PHP between 5.3 and 5.3.7.
The problem with other algorithms like SHA* or MD5 is, that they are ways too fast. It is possible to calculate about 3 Giga SHA-1 per second with common hardware, that makes brute-forcing too easy. To test a whole english dictionary you would need only a fraction of a millisecond. That's why one should use a hash algorithm with a cost factor like BCrypt or PBKDF2, they allow to control the necessary time to calculate a single hash.
Look at this question:
https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512
You can use hash function
http://www.php.net/manual/en/function.hash.php
Use salt and sha256 encryption algorithm
<?php
// create user
$password = $_POST['password'];
$salt = mcrypt_create_iv(22, MCRYPT_DEV_URANDOM);
$pass = hash("sha256", $salt.$password.$salt);
// save salt and password hash into database
// to validate user
// 1 - get salt and password hash from database
// 2 - prepend and append salt to the posted password
// 3 - encrypt with the same algorithm
// 4 - compare with stored password hash.
I've made encrypting of the password in my register script and they are stored in the database, and I have to use them to login, so I would want to use the unencrypted ones to login. I've read some of the threads in here but nothing is helping me. How can I add it in my login.php? The salt is also stored in the database.
This is my register.php script for encrypting
$hash = hash('sha256', $password1);
function createSalt()
{
$text = md5(uniqid(rand(), TRUE));
return substr($text, 0, 3);
}
$salt = createSalt();
$password = hash('sha256', $salt . $hash);
and this is my login.php with season
//Create query
$qry="SELECT * FROM member WHERE username='$username' AND password='$password'";
$result=mysql_query($qry);
//Check whether the query was successful or not
if($result) {
if(mysql_num_rows($result) > 0) {
//Login Successful
session_regenerate_id();
$member = mysql_fetch_assoc($result);
$_SESSION['SESS_MEMBER_ID'] = $member['id'];
$_SESSION['SESS_FIRST_NAME'] = $member['username'];
$_SESSION['SESS_LAST_NAME'] = $member['password'];
session_write_close();
header("location: profile.php");
exit();
}
else {
//Login failed
//error message
}
else {
die("Query failed");
}
These examples are from php.net. Thanks to you, I also just learned about the new php hashing functions.
Read the php documentation to find out about the possibilities and best practices:
http://www.php.net/manual/en/function.password-hash.php
Save a password hash:
$options = [
'cost' => 11,
];
// Get the password from post
$passwordFromPost = $_POST['password'];
$hash = password_hash($passwordFromPost, PASSWORD_BCRYPT, $options);
// Now insert it (with login or whatever) into your database, use mysqli or pdo!
Get the password hash:
// Get the password from the database and compare it to a variable (for example post)
$passwordFromPost = $_POST['password'];
$hashedPasswordFromDB = ...;
if (password_verify($passwordFromPost, $hashedPasswordFromDB)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
According to php.net the Salt option has been deprecated as of PHP 7.0.0, so you should use the salt that is generated by default and is far more simpler
Example for store the password:
$hashPassword = password_hash("password", PASSWORD_BCRYPT);
Example to verify the password:
$passwordCorrect = password_verify("password", $hashPassword);
array hash_algos(void)
echo hash('sha384', 'Message to be hashed'.'salt');
Here is a link to reference http://php.net/manual/en/function.hash.php
You couldn't login because you did't get proper solt text at login time.
There are two options, first is define static salt, second is if you want create dynamic salt than you have to store the salt somewhere (means in database) with associate with user.
Than you concatenate user solt+password_hash string now with this you fire query with username in your database table.
I think #Flo254 chained $salt to $password1and stored them to $hashed variable. $hashed variable goes inside INSERT query with $salt.
You can't do that because you can not know the salt at a precise time. Below, a code who works in theory (not tested for the syntaxe)
<?php
$password1 = $_POST['password'];
$salt = 'hello_1m_#_SaLT';
$hashed = hash('sha256', $password1 . $salt);
?>
When you insert :
$qry="INSERT INTO member VALUES('$username', '$hashed')";
And for retrieving user :
$qry="SELECT * FROM member WHERE username='$username' AND password='$hashed'";
I have registered a new user and saved the username, password & salt in the DB using the following hashing method:
if(isset($_POST['register']))
{
$password = $_POST['password']
function sanitize($data)
{
$data=trim($data);
$data=htmlspecialchars($data);
$data=mysql_real_escape_string($data);
return $data;
}
$password = sanitize($password);
function createSalt()
{
$salt = bin2hex(mcrypt_create_iv(32,MYCRYPT_DEV_URANDOM));
$hash = hash("sha256", $salt);
$final = $salt.$hash;
return $final;
}
$hashedPassword = hash("sha256", $password);
$salt = createSalt();
$hashedPassword = hash("sha256", $hashedPassword.$salt);
$query = sprintf("INSERT INTO users(username, password, salt) VALUES('%s','%s','%s')",$username, $hashedPassword, $salt);
}
And Later while trying the login.php, I am entering the same password which I saved during registration and using the below code to check if the entered password is the same as the one in the DB
if(isset($_POST['login']]))
{
$password = $_POST['password']
function sanitize($data)
{
$data=trim($data);
$data=htmlspecialchars($data);
$data=mysql_real_escape_string($data);
return $data;
}
function validateUser()
{
session_regenerate_id (); //this is a security measure
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
}
$password = sanitize($password);
$query = sprintf("SELECT * FROM users WHERE username = '%s'",$username);
$sql = mysql_query($query);
$count = mysql_num_rows($sql);
$row = mysql_fetch_array($sql);
if($count<1)
{
echo $count;
unset($_POST['login']);
header("location:login.php");
exit;
}
$hash = hash("sha256", $password);
$salt = $row['salt'];
$hash = hash("sha256",$hash.$salt);
echo $hash."<br />".$row['password']."<br /><br />";
if($hash != $row['password'])
{
unset($_POST['login']);
header("location:login.php");
exit;
}
else
{
validateUser();
unset($_POST['login']);
header("location:index.php");
exit;
}
}
These passwords are not getting matched.
Kindly let me know what's wrong in this code.
There is nothing wrong with your code.
the salt value stored in the database is truncated because the varchar value is low increase the varchar value of your salt column to 200-300 something and than try this.. it will run fine.
I facepalmed when I found out this was screwing the result..
Dins
Actually i didn't see why this should not work, the code you have shown, should produce the same value, maybe you could check, whether the salt you read from the database is really the same as you wrote to the database.
Nevertheless i would not engourage to go further on this route, there are quite a lot of problems here.
First of all, SHA-256 is not a good choice to hash passwords, instead use a slow key-derivation function like BCrypt.
You should not escape input data without need, and if you need to escape them, you should do it only for the specific target system (htmlspecialchars and mysql_real_escape_string make no sense if you are going to calculate a hash anyway).
To create a salt, you use the random source, that is good. Using a hash afterwards creating the salt, will in no way make the salt more random.
There is no need to have two separate fields for password and salt in the database. Php's crypt() function will create a hash value, that already contains the salt.
I would invite you to read this tutorial about hashing passwords, you will find a PHP example too, and i would recommend to use the phpass library.
I am fairly new to php security, and for my site, I was a sign up and login, and I want to add md5 their passwords, but I can't find anywhere which has a clear guide on what needs to be added to the sign up, and what needs to be added to the login files, and/or the database, as I say I am fairly new to php in terms of web security, so I am in need of some help, here's part of what I have on my sign up form:
$error = $user = $pass = "";
if (isset($_SESSION['user'])) destroySession();
if (isset($_POST['user']))
{
$user = sanitizeString($_POST['user']);
$pass = sanitizeString($_POST['pass']);
if ($user == "" || $pass == "")
{
$error = "Not all fields were entered<br /><br />";
}
else
{
$query = "SELECT * FROM members WHERE user='$user'";
if (mysql_num_rows(queryMysql($query)))
{
$error = "Username already taken<br /><br />";
}
else
{
$query = "INSERT INTO members VALUES('$user', '$pass')";
queryMysql($query);
die("<h4>Account created</h4>Please Log in.");
}
}
}
I just need an example or a good guide of what I need to do to get it working correctly.
I think you're looking to salt and then hash your passwords. Simply add a string of your choosing to the front (and if you wish, to the end) of your password before hashing it using MD5.
e.g.
$pass = 'mypassword';
$salt = 'S%gh3578'; //anything you want
$pepper = 'w890rrk'; //anything you want
$query = "INSERT INTO members VALUES('$user', md5('".$salt.$pass.$pepper."'))";
queryMysql($query);
This will store the password in the database using salted MD5 encryption that cannot be reversed using a lookup table of common passwords using unsalted MD5 encryption.
To check if a password is valid, you do something similar:
$passToCheck = 'something';
$correctMD5 = (retrieve hash from db)
if($salt.$passToCheck.$pepper == $correctMD5)
{
//valid login
} else {
//login failure
}
You can for example md5($pass) before you insert and when the user logs in, you md5 again and check that the values are the same. There is no way to de-md5, so you will usually check the md5 input against the md5 DB value.