I use this statement to hash the password with Phalcon:
$hashedPassword= $this->security->hash($password)
but this statement returns different results with the same password.
Example:
Set $password=123
I get $hashedPassword with the following values:
$2a$08$T2Rf9IcQHTj7TpY.gsfGiexZ35/KK9kS3fLElxaw8LGXhjnE01f5K
and
$2a$08$E2mjApECMbRKQFZodgLkEOpDLSV/tEjTe1HV3q2LLG9UINj9M9GBm
and
$2a$08$aZmgsMmG2xRueVzP6tkx2ucWGPZMzUwIccXbLJnqoRwDsSnT4zc.q
Here is the code I use for checking user's password,
please let me know what am I missing.
if ($this->request->isPost() == true)
{
$email = $this->request->getPost ("email");
$password = $this->request->getPost ("password");
$conditions = "email = ?1 AND admin = ?2";
$parameters = array(1 => $email, 2 => 1);
$users = Users::findFirst(array(
$conditions,
"bind" => $parameters
));
if($users)
{
$security = new Phalcon\Security();
$checkHashValue = $security->checkHash($password, $user->password);
if($checkHashValue)
{
$this->flash->success($users->fullname);
}
else
{
//Print debug information
$hash = $security->hash($password);
$checkHash = $security->checkHash($password, $hash);
$this->flash->error("Password: ". $password.
"<br/>Hash: " . $hash . "<br/>Check Hash: " . $checkHash .
"<br/>Check HashValue: ". $checkHashValue);
}
}
else
{
$this->flash->error($password);
}
}
SOLUTION: I have a typo in my variable "user" instead of "users".
That's how it is supposed to work. It creates a random hash each time. To check the password use security->checkPassword()
SOLUTION: I have a typo in my variable "user" instead of "users".
Related
I have three files that are relevant for this part of my login scenario:
/project/index.html
/project/api/user/login.php
/project/api/objects/user.php
The index.html has a simple login form in it, calling the ./api/user/login.php.
In this form I have a checkbox that is an option for the user in order to stay logged in or not.
If the user has selected this option, with every login, I would like to check if the credentials are correct (login function -> stmt1 in user.php) as well as to update the lastlogin (datetime), the identifier and securitytoken if the checkbox was set (login function -> stmt2 in user.php).
The user.php is included_once in the login.php that gets the values out of the index.html form and sends them to the login() function in the user.php.
Depending on the functions return value, the login.php decides if the login was successful or not.
The login itself (stmt1) works, but the update of lastlogin, identifier and securitytoken (stmt2) doesn't.
login.php
session_start();
// include database and object files
include_once '../config/database.php';
include_once '../objects/user.php';
// get database connection
$database = new Database();
$db = $database->getConnection();
// prepare user object
$user = new User($db);
// set ID property of user to be edited
$user->username = isset($_GET['username']) ? $_GET['username'] : die();
$user->password = base64_encode(isset($_GET['password']) ? $_GET['password'] : die());
$user->remember = isset($_GET['remember']) ? $_GET['remember'] : die();
$stmt1 = $user->login();
if($stmt1->rowCount() > 0){
// get retrieved row
$row1 = $stmt1->fetch(PDO::FETCH_ASSOC);
$_SESSION['userid'] = $row1['uid'];
// create array
$user_arr=array(
"status" => true,
"message" => "Login erfolgreich!",
"uid" => $row1['uid'],
"username" => $row1['username']
);
$stmt2 = $user->login();
$row2 = $stmt2->fetch(PDO::FETCH_ASSOC);
print_r($row2);
// create array
$user_arr=array(
"lastlogin" => $row2['lastlogin']
);
}
else{
$user_arr=array(
"status" => false,
"message" => "Benutzername und/oder Passwort nicht korrekt!",
);
}
// make it json format
print_r(json_encode($user_arr));
?>
user.php
function login(){
// select all query
$query1 = "SELECT
`uid`, `username`, `email`, `password`, `created`, `lastlogin`
FROM
" . $this->table_name . "
WHERE
username='".$this->username."' AND password='".$this->password."'";
// prepare query statement
$stmt1 = $this->conn->prepare($query1);
// execute query
$stmt1->execute();
return $stmt1;
// set up the remain logged in function
if(isset($this->remember)) {
$identifier = random_string();
$securitytoken = random_string();
$remember = ",identifier='".$identifier."',securitytoken='".$securitytoken."'";
setcookie("identifier",$identifier,time()+(3600*24*365)); //1 year valid
setcookie("securitytoken",$securitytoken,time()+(3600*24*365)); //1 year valid
} else {
$remember = "";
}
// update last login
$query2 = "UPDATE
" . $this->table_name . "
SET
`lastlogin` = '".date("Y-m-d H:i:s")."'
".$remember."
WHERE
username='".$this->username."' AND password='".$this->password."'";
// prepare query statement
$stmt2 = $this->conn->prepare($query2);
// execute query
$stmt2->execute();
return $stmt2;
}
function random_string(){
if(function_exists('random_bytes')) {
$bytes = random_bytes(16);
$str = bin2hex($bytes);
} else if(function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes(16);
$str = bin2hex($bytes);
} else if(function_exists('mcrypt_create_iv')) {
$bytes = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$str = bin2hex($bytes);
} else {
//secret key should have >12 random chars
$str = md5(uniqid('SECRET KEY', true));
}
return $str;
}
In the user.php after return $stmt1;
The code is returned and the cookies are not set
I would do this... Check login... If true, save cookies with id and token
And then periodically check if token and id correspond... If so... Just UPDATE the last login time.
Note: your prepared statement is vulnerable!! Dont append the parameters with '.' use placeholders instead, and dont encode the password, is better to hash it... Then compare hashes
I've searched high and low for this topic, and no one has the same issue I'm experiencing that I could find.
I'm creating a user in a MySQL table, with a hash from password_hash with a strength of 10.
I've been having hell getting it to validate, and have a test script made to actually validate my findings. Here is the script:
public function testAction(){
$data = new dataHandler;
$data->table = "access";
$hash1 = $data->insert(array('email'=>'test6#test.com', 'password'=>'ABC123.abc', 'password_confirm'=>'ABC123.abc', 'alias'=>'ABC123.abc'));
$res = $data->find(array('email'=>'test6#test.com'));
$hash2 = $res[0]['hash'];
$test = password_verify('ABC123.abc', $hash1);
$test2 = password_verify('ABC123.abc', $hash2);
var_dump($test);
echo "<br>";
var_dump($test2);
echo "<br><br>";
echo "Length: " . strlen($hash1) . "<br>{$hash1}<br>Length: " . strlen($hash2) . "<br>{$hash2}";
die();
}
To verify that my script wasn't somehow doing something weird when storing, I made my hash method (called from within the insert() method dynamically) echo out the hash directly:
public function createHash($password){
$hash = password_hash($password, HASH);
echo "Length: " . strlen($hash) . "<br>$hash<br>";
return $hash;
}
Here's the insert method. cleanData simply unsets anything not available in a describe - it is not changing any values whatsoever. Warning, it's terribly ugly presently due to a lot of debugging and such:
public function insert($data){
if(!is_array($data)){
return false;
} else {
$this->openDb();
$ins = "";
$fs = "";
$data = $this->cleanData($data);
foreach($data as $key => $field){
if($key == "password"){
$auth = new authorization;
$key = "hash";
$field = $auth->createHash($field);
$data['hash'] = $field;
unset($data["password"]);
}
$ins .= ":{$key}, ";
$fs .= "`{$key}`, ";
//$data[$key] = $this->DBH->quote($field);
}
$ins = rtrim($ins, ", ");
$fs = rtrim($fs, ", ");
try {
# the shortcut!
$this->DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$STH = $this->DBH->prepare("INSERT INTO `" . $this->table . "` ($fs) value ($ins)");
$STH->execute($data);
$id = $this->DBH->lastInsertId();
$this->closeDb();
return $data['hash']; //Debugging
return $id;
} catch(PDOException $e) {
$this->errHandler($e->getMessage());
}
}
}
Now, here's the output:
Length: 60
$2y$10$wGJxGjK4Lz4FgZ3OZJjBo.9lF7LE90p3Q5inOsBROQTU5FBVdj1LK
bool(true)
bool(false)
Length: 60
$2y$10$wGJxGjK4Lz4FgZ3OZJjBo.9lF7LE90p3Q5inOsBROQTU5FBVdj1LK
Length: 60
$2y$10$wGJxGjK4Lz4FgZ3OZJjBo.9lF7LE90p3Q5inOsBROQTU5FBVdj1LK
As you can see, both password_verify attempts fail. The first comes from the hash generation without any further manipulation, the second comes from the database.
What am I doing wrong?
The only thing I could find when searching was people testing and using double quotes, or random human error. This, however, doesn't appear to me to be either of those two.
That password hash is for the empty string, try it yourself:
<?php
echo password_verify('', '$2y$10$4Y7kQNP/6XyBtQQ4zPI6ZuaelCjHdWE.kBRTUVk56J7PV4BQYWoUS')?'Y':'N';
?>
Make sure you're passing createHash a valid $password.
So i am a newbie in php.
I have database with a pseudo and pwd table, the passwords are crypted with password_hash.
This is how i send new user in my database :
<?php
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$pwd = password_hash($pwd, PASSWORD_BCRYPT, $options);
$insert_query = "insert into user values ('$pseudo','$pwd','$mail')";
$mysqli->query($insert_query);
It's working, then when i want to log as user wich is in the database, i searh the password associated with the pseudo i write in the form, once i have the password i use it with the noon crypted password (the one i get by POST)
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$pwd2 = password_hash($pwd, PASSWORD_BCRYPT, $options);
$sql_log = "select mdp from user where pseudo ='$pseudo'";
$mysqli->multi_query($sql_log);
if($res = $mysqli->use_result()) {
while($row = $res->fetch_row()) {
echo $row[0]."<br/>";
}
$res->close();
echo $pwd2."<br/>";
echo $pwd."<br/>";
if(password_verify($pwd,$row[0])) {
$mysqli->close();
$_SESSION['pseudo'] = $pseudo;
die("<script>location.href = 'homepage.php'</script>");
}
else
echo "putin";
}
But it's not working, ive read other topics about it but nothing helps me.
Ok i've found my problem, i don't know if it will be usefull for others or if i make understandable but i was really dumb.
while($row = $res->fetch_row()) {
echo $row[0]."<br/>";
}
$res->close();
echo $pwd2."<br/>";
echo $pwd."<br/>";
if(password_verify($pwd,$row[0])) {
$mysqli->close();
$_SESSION['pseudo'] = $pseudo;
die("<script>location.href = 'homepage.php'</script>");
}
i created row in the while and when i check his value out of the while it returns 0, so the second argument that i was passing in password_verify was null...
ty
I have successfully run ldap_connect and ldap_bind commands in my php script. Now I need to get guvenName by user id. How can i do this.
$username = $_POST['username'];
$password = $_POST['password'];
define('LDAP_SERVER', 'localhost');
define('LDAP_PORT', 389);
define('LDAP_TOP', 'ou=people,dc=domain,dc=com');
$ds = ldap_connect(LDAP_SERVER, LDAP_PORT);
if (!$ds) {
echo "FALSE";
}
if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
#ldap_close($ds);
echo "FALSE";
}
$dn = 'uid=' . $username . "," . LDAP_TOP;
if (!ldap_bind($ds, $dn, $password)) {
echo "FALSE";
}
In general it's quite simple
public function getusercn($accountname)
{
$filter_person = "(&(sAMAccountName={$accountname}))";
$sr_person = ldap_search($this->ds_ad,$this->base_user_dn,$filter_person);
$sr = ldap_get_entries($this->ds_ad, $sr_person);
$attr = $sr[0]["givenName"][0];
return $attr;
}
$this->ds_ad - it's $ds in your code
$this->base_user_dn - is base OU from which you want to search (like LDAP_TOP in your case)
sAMAccountName - is "user id" attribute in your case uid
givenName - is attribute what you are looking for
All of attributes are already in $sr variable, so you can use var_dump to inspect all content.
I used this hash function for a while (got it from the internet). The thing is it used to work immediately but now it is complaining about a paramter. The following is the code:
function generateHash($plainText, $salt = null)
{
if ($salt === null)
{
$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
}
else
{
$salt = substr($salt, 0, SALT_LENGTH);
}
return $salt . sha1($salt . $plainText);
}
So I would use this code in the method call:
validateUserInput($userid, $pass);
and validateUserInput is:
function validateUserInput($username, $password)
{
//$username = mysql_real_escape_string($username);
//$password = mysql_real_escape_string($password);
if(!$username || !$password)
{
//$errors['credentials'] = 'Missing Credentials!';
//$_SESSION['errors_array'] = $errors;
//echo $errors['credentials'];
header("LOCATION:XXXXXXX.php");
}
$local_salt = generateHash($password);
//echo $local_salt;
$groupid;
if($username != null && $password !=null)
{
connectToServer();
$result = mysql_query("SELECT * FROM users WHERE hashkey = '{$local_salt}'");
while($row_access = mysql_fetch_array($result))
{
$groupid = $row_access['groupid'];
}
if(!isset($result))
{
$errors['not_found_user'] = 'No Users Found with Provided Credentials!';
//$_SESSION['errors_array'] = $errors;
$userfound = 0;
$_SESSION['user_available'] = $userfound;
}elseif(isset($result)){
$_SESSION['user_logged'] = array('username' => $username, 'password' => $password, 'salt' => $local_salt, 'groupid' => $groupid);
$userfound = 1;
//echo "stored";
$_SESSION['user_available'] = $userfound;
}
}
}
finally the error is:
Warning: substr() expects parameter 3 to be long, string given in /home/XXXX.php on line 64
This is pointing to the function generateHash()
The error itself tells you everything. The constant SALT_LENGTH is not a long. I suspect it's not defined at all, so PHP converts the bare string to a string ("SALT_LENGTH") and passes that to substr(), which complains.
That being said... This code is dangerously wrong:
if(!isset($result)): Really? This condition will always be false because $result will always be set (unless you run into a problem with mysql_query(), but that doesn't tell you anything about the valididty of the login). And since mysql_query() never returns null, no logins will ever be rejected.
This query:
SELECT * FROM users WHERE hashkey = '{$local_salt}'
Is invalid. $local_salt = generateHash($password);. From the generateHash function, if a salt is not given, one will be randomly created for you. Thus, every call to generateHash will generate a new hash, which means it can't be compared to anything in the database.
On the basis of the two (very) egregious mistakes above, I would throw away this piece of code for good.
The correct way to check for a valid hash when a salt is used is something like:
$_SESSION['user_logged'] = null;
// fetch hashed pw from db, where username is the submitted username
$result = mysqli_query("SELECT hash FROM users WHERE username = '{$username}'");
if ($result->num_rows != 0)
{
$row = $result->fetch_assoc();
$hash = $row['hash'];
$salt = substr($hash, 0, SALT_LENGTH); // extract salt
if (generateHash($password, $salt) == $hash)
{
// login successful.
$_SESSION['user_logged'] = $username; // don't store passwords here
}
}
// if $_SESSION['user_logged'] is not set, the login failed
if (!isset($_SESSION['user_logged']))
{
// you *don't* want to tell people which one (login or pw) is invalid
echo 'Invalid login or password';
}
Note: It's very important that the SALT_LENGTH is at most 32, or this won't work because of the way generateHash() is implemented.
Clearly SALT_LENGTH is not an integer. Find where it's defined and correct this.
Instead of making a new hashing function each time you write an application , you should utilize the one provided to you by php: crypt() ( i would recommend to go with any blowfish or sha256+ hash ).
And when selecting information from database, you should select it by username and then, with php, check if hash fits the password.