My problem is that I can still log in even I typed in the wrong password. I can't seem to know if there's a problem on how I decoded the password.
encryption key:
$config['encryption_key'] = 'formcreatormj';
Log in code:
function login($email,$password){
$pw = $this->encrypt->decode($password);
$this->db->where('email',$email);
$this->db->where('password', $pw);
$query=$this->db->get('user');
if($query->num_rows()>0){
foreach($query->result() as $rows){
//add all data to session
$this->addSession($rows->id, $rows->username);
}
return true;
}
return false;
}
You should not be using the Encryption class for working with passwords. Passwords should be hashed one-way, to prevent the original plaintext from being recovered trivially. Codeigniter's Encryption class provides two-way encryption and is unsuitable for passwords.
Instead, you should be working with bcrypt - How do you use bcrypt for hashing passwords in PHP?
You are going about the hashing wrong. Typically you'd store the hash of the password in the database. i.e. when the user signs up, you $this->encrypt->encode() the password and store that in the database.
Next time the user tries to log in, you again hash the password they enter in the login and compare that to the hashed password in the database.
But, since, by default, codeigniter uses mcrypt, these hashes won't match. So what you need to do is pull the hash from the db, decrypt that and compare that with the submitted password.
$this->db->where('email',$email);
$query = $this->db->get('user')->row(0);
if($this->encrypt->decode($query->password) == $password){
//password OK
}else{
//password not OK
}
What you are doing is trying to decrypt the submitted password which isn't encrypted.
Edit: strongly agree with #xiankai You really should be using bcrypt for passwords.
Related
I created user and I gave him password 'secret'.
The hash that was generated by the registration process is
$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm
I wanted to generate it in the code so I used Hash::make('secret') and I got:
$2y$10$Hnbg7DCp2VObns4cbr580uo9VTYgzJF2BSNSpA7S8BYjkAgfUlH.G
finally I used bcrypt('secret') and I got:
$2y$10$5g1bhkHB7kRk8SkM3yS/YOifsEesjZ31YeYnRlE.bxSBmZutVCuui
These are all different hashes, How can I generate one that would let me change password inside my code?
It's because bcrypt doesn't work as SHA-256, it uses a key that would change the result of the hash itself for the same string.
In Laravel, you can use Hash::check('plain-text', $hashedPassword) to check the password, but you will never have the same result for the same password. check here
You can use bcrypt(secret") and leave it at laravel and test it (everything is working).
It works as intended, bcrypt doesnt always generate the same hash. Laravels Hash::check() function will return true for any valid hash of the given password.
For mor informations, look here: https://stackoverflow.com/a/8468936/6622577
Bycrypt is a more secure password hashing algorithm. Unlike md5() or SHA1() bycrypt does not always generate the same hashed value for a specific string.
So when you are storing the hashed password in the database you will use
$password = bcrypt($input['password']);
Afterwards, when you wish to check at the time of login you simply set the plain-text password (As you might be getting it from user input) and run a function called Auth::attempt() to match the password.
$userdata = array(
'username' => $input['username'],
'password' => $input['password'],
);
if (Auth::attempt($userdata)) {
// Password matched
}
And if you want to explicitly check the plain-text password corresponding to its hash then use Hash::check() as below:
Hash::check('plain-text-password', 'hashed-password);
Could it be a good idea to "re-hash" a password after every login and save the new hash into the database? Are there any pros and cons for this in terms of modern security standards?
Here a minimal code example in PHP:
function login(string $username, string $password): bool {
// function arguments coming from $_POST
$user = User::findByUsername($username);
if($user) {
if(password_verify($password, $user->password)) {
// re-hash password ...
$user->password = password_hash($password, PASSWORD_DEFAULT);
// ... and save it in database
$user->save();
return true;
}
}
return false;
}
Rehashing the password after each successful login does not increase security.
If the function password_hash() would use a fix global salt, the hash would look exactly the same for the same password. So an attacker would not even notice any difference in the database.
Though, the function password_hash() will generate a long enough unique salt if used properly, and several hashes of the same password with different salts will not make brute-forcing easier.
So while rehashing does not weaken security, it does not help in any way either, it is better to use the time to increase the cost factor.
There's no need to rehash your user's password every time they login. It doesn't improve your security whatsoever.
In setting up a "change password" feature for a site I have a secondary password entry (where you need to enter your password again before you can change it).
I need to be able to check the user's current password (hashed using Bcrypt) against the password that has been entered.
In my controller action I have:
$currentPassword = $request->request->get('password');
$encoder = $this->container->get('security.password_encoder');
$encodedPassword = $encoder->encodePassword($user, $currentPassword);
if($encodedPassword == $user->getPassword()) { // these don't ever match.
// ...
}
encodePassword(...) produces a digest of the password that was entered, but it's not the same as the saved password (the plaintext is the same), so I'm thinking that a different salt is being applied and therefore producing the mismatch.
Since Bcrypt incorporates the salt in the password digest, I'm not saving it anywhere.
How can I check if the entered plaintext password matches the stored Bcrypt digest in Symfony 3?
I am not using FOSUserBundle.
You can compare the $currentPassword password with the stored one using the isPasswordValid method of the encoder service:
$encoderService = $this->container->get('security.password_encoder')
and then pass the user object as first argument of the method:
$match = $encoderService->isPasswordValid($userObject, $currentPassword)
that will returns true if the comparison match or false otherwise.
What type of hashing algorithm is used by default for passwords in Laravel. If we want to change the password in the database then how can we identify the hash type of the password?
According to Laravel Documentation :
The Laravel Hash facade provides secure Bcrypt hashing for storing
user passwords. If you are using the AuthController controller that is
included with your Laravel application, it will be take care of
verifying the Bcrypt password against the un-hashed version provided
by the user.
Likewise, the user Registrar service that ships with Laravel makes the
proper bcrypt function call to hash stored passwords.
Hashing A Password Using Bcrypt
$password = Hash::make('secret');
You may also use the bcrypt helper function:
$password = bcrypt('secret');
Verifying A Password Against A Hash
if (Hash::check('secret', $hashedPassword))
{
// The passwords match...
}
Checking If A Password Needs To Be Rehashed
if (Hash::needsRehash($hashed))
{
$hashed = Hash::make('secret');
}
You can also use laravel/tinker to update/create/delete/etc data in the DB table from console, for example:
php artisan tinker
>>$user = App\Models\User::find(2);// or User::find(2)find user with id 2
>>$user->password = bcrypt('test83403'); //change password
>>$user->save(); //save the new change
I Have the following class to validate the user Login,
class Validation_model extends CI_Model {
public function validateLogin($userid,$userpass){
$this->load->library('encrypt');
$this->load->database();
$encrypted_string = $this->encrypt->encode($userpass);
$this->db->select('*');
$this->db->from('ecom-user');
$this->db->where('userid', $userid);
$this->db->where('userpassword', $encrypted_string);
$result = $this->db->get();
echo $result->num_rows();
}
}
But when even I entered a valid userid & password it returns the row count as 0, Please help me with this, where I have done the mistake?
It does not work because you are encrypting the password.
The encryption function used by CodeIgniter uses a random initialization vector (IV) every time it encrypts something, which means that the cipher-text (the encrypted text) will be different every time it is encrypted.
When dealing with passwords you need to hash them, not encrypt them. They are related but they are not the same thing.
Wikipedia article on cryptographic hash functions
Page on PHP.net on password hashing
Documentation on PHP's native password hashing API
Compatibility library for the native API (if you have PHP <5.5.0)
PHPass implementation for CodeIgniter on Github (if you have PHP <5.5.0)
If you have PHP >=5.5.0 then you can do:
$hashed_password = password_hash($userpass, PASSWORD_DEFAULT);
// ...
$this->db->where('userpassword', $hashed_password);
For this to work you also need to re-hash the passwords in your database.