How to compare passwords (Bcrypt hashes) in Symfony 3? - php

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.

Related

Creating password hash in Laravel project

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);

Default hash type of passwords in Laravel

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

Use laravel 4 passwords with phalcon

I am trying to use my stored passwords from Laravel 4 in a fresh Phalcon Installation. I have no idea whether this is possible and tried it this way in the SessionController of the Phalcon sample-apllication INVO:
#$password = sha1($password);
$password = password_hash($password, PASSWORD_BCRYPT);
Can I use another Hash-Algorythm in phalcon, that fits to Laravel 4 Passwords, or can I convert the hashes somehow?
You should be able to use laravel hashses - all you need to do is to check how Laravel is creating and checking them.
Check this code from BCryptHasher::make() and this for validating.
The problem is that in Laravel this algorithm is a bit different. First is obtaining user from database then checking if password is the same with password_verify. While in INVO you first hash the given password and then you search for a user with given email and hash - if it finds anything then it can log user. Below should do the trick knowing the $cost value from Laravel settings (class defaults to 10).
$password = password_hash($value, PASSWORD_BCRYPT, array('cost' => $cost));
Edit: while above would be true for SHA1 & similar. The INVO code should be changed to match the login algorithm in Laravel and BCrypt itself:
$user = Users::findFirst(array("email = :email: AND active='Y'", 'bind' => array('email' => $email));
if ($user != false && password_verify($user->password, $this->request->getPost('password'))) {
// login user
}
Laravel is using BCrypt for a reason - it is generally very good choice for hashing so you should stick to it.
Anyway you could write a password migration which will do upon each user successful login:
validate user password using old hashing algorithm
checks if User has migrated it's password (ie by checking some database field - or separated table)
hash given password with new algorithm
store new hash and update user table (with information that hash has been changed)
Which is rather complicated and should be needed only when migrating to "better" algorithm.

Compare password with Hashed + Salt generated by Symfony 2

I'm trying to authenticate users in Mysql database generated by Symfony 2. In Security.yml I have this :
security:
encoders:
"FOS\UserBundle\Model\UserInterface": sha512
In User Table there is 2 fields : Salt and Password.
All passwords are like that :
YqkYUe0pV/TAw12aG2UcBax0hnJNeHez/S0uBGbnDDBxWD2Yeetqm4DfMn/8WKILIeRpM7ncTJ9coYOiNPGeOA==
I'm working on a webservice to authenticate users using PHP. I don't which functions do I have to use to compare plain password with the encrypted ones?
You have to get the password encoder factory from the container.
You can do so like this :
$factory = $container->get('security.encoder_factory'); //$container refers to your container, it can be also $this->container
$user = new Your\Bundle\Entity\User();
$encoder = $factory->getEncoder($user);
$encodedPassword = $encoder->encodePassword($nonEncodedPassword, $user->getSalt());
This should be enough. Of course you can set "by hand" the second encodePassword parameter as its the salt used to encode all paswords. It's usually defined in your user implementation class, that's why we give here an entity instancied object.
This is the class that handles the sha512 encryption in Symfony2
https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php

Using encryption class in Codeigniter

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.

Categories