How do BCryptPasswordEncoder check the passed plain password while using salt? - bcrypt

I've check the source of BCryptPasswordEncoder and found it won't return generated random salt. Then, while we check the plain password later, we don't know which salt did this user use at that time, so how can BCryptPasswordEncoder check whether plain password and encrypted password are the same?

Related

laravel 5.6 convert hashed password to normal password?

There is no option to convert hashed text back to plain text. Thats the reason why we use that method to store password - only the author of a password can know the real value - nobody else (developers and someone who can stole passwords). The popular method used to break hashed password is called "brute force attack" and is based on comparing already known hashed values of popular passwords to existing ones in database.
Now i need to show current password when user change password. but hash password cant not return back.
how to solve this issue?
convert hashed password to normal password?
Encryption is a two-way function; what is encrypted can be decrypted with the proper key.
Hashing is a one-way function that scrambles plain text to produce a unique message digest. With a properly designed algorithm, there is no way to reverse the hashing process to reveal the original password.
Now i need to show current password when user change password. but hash password cant not return back. how to solve this issue?
You do not need to show the password to anyone, including the owner of the password.
If you want to check, you can use check method, allows you to verify that a given plain-text string corresponds to a given hash.
if (Hash::check('plain-text', $hashedPassword)) {
// The passwords match...
}

Laravel Password Encryption Parameters to decrypt the code

I have some different requirement, i don't want to decode the password, but i am building some other app based on SAME DATABASE for LOGIN so what i can do to "encrypt the password value so that it matches the backend password encrypted code".
I want to provide LOGIN from CODEIGNITOR app where data base is created by admin app in LARAVEL ... this is the issue...
So through CodeIgnitor if someone is LOGIN the password will be encrypted equivalent hash encrypted laravel application code.
The Encrypted Password is
$2y$10$cwd15HRgON0ytqkkV5F9zupfUOkqaii7fpbB9Kjd9I7W46LRYY0Km
And the real PASSWOORD is
123456
Please help...
Caddy DZ's answer is right, but to better answer your question you should know that every time you generate a new password with bcrypt function, a new random salt is used.
This leads you to end up getting a different hash for the same password each time you generate one.
The only way you have to verify the correctness of the password, is to use a built-in php function called password_verify.
That function will hash your password (that you provide as a second argument) with the same salt that has been used to generate the stored password (the salt to use is stored in the password hash) you already have in the database:
$password = '123456';
$saved = 'your stored hash';
if (password_verify($password, $saved)) {
echo 'Correct password.';
}
You can check the documentation about password_verify
This is not standard encryption that can be decrypted, this is hashing which is only one (1) way encryption..
To make this work in, you need to use the same hashing algorithm between the two apps (Laravel and CodeIgniter)
For instance laravel uses bcrypt by default to hash the password, so you need to configure CodeIgniter to use the same or vice versa.
bcrypt for codeigniter

Laravel 5.8 - save user emails encrypted

I'm looking for a way to encrypt the user emails in the database. Since Encrypt always generates a different string, it fails.
So I took sha1.
in AuthenticatesUsers I've changed the credentials method to:
protected function credentials(Request $request)
{
return ['email' => sha1(strtolower($request->email)), 'password' => ($request->password)];
}
This works great for the login/registration. But there are problems with resetting the password.
Resetting the password uses the SendsPasswordResetEmails trait.
There it this credentials method:
protected function credentials(Request $request)
{
return $request->only('email');
}
This always fails, cause it does not find the user (cause the user is saved with sha1 email)
if I change it to return ['email' => sha1(strtolower($request['email']))];
I get the error, that the email is not in the right RFC standart, to send a email. The Problem is, I don't really find the place, where laravel is searchig for the user with this email. Anyway, I don't really have a clue, how I can solve this problem at all.
I want to encrypt the email itself, because in germany there is a law which forces us to store personal data encrypted, like the email.
First thing to say is that Hashing is not the same as Encryption.
Encryption is a two way function, that is if you can encrypt an email you can decrypt it with a reverse function, if you know the encryption key, and obtain the original email.
Hashing is a one way function, that is if you hash a password you can't obtain the original password with a reverse function, you can only verify that, when you input the password again, the hash you obtain matches the original hash, so you only know that the two password are identical.
You usually store password hashed, not crypted, so even the administrator can't recover the original password, he con only verify that a input from a user has a hash that match the original password he entered.
You can read more in this stackoverflow question: Difference between Hashing a Password and Encrypting it.
The sha1() is a hashing function, so is not reversable, you can't obtain the original email.
Laravel has the functions encrypt() and decrypt() to encrypt things, see the docs on encryption, and has the functions Hash::make() to hash a password and Hash::check() to verify the password, see the docs on hashing.
So if you want to encrypt the emails, not hashing them with sha1, you should use encrypt() and decrypt().
The best way for you is to use mutators, i.e.:
public function getEmailAttribute($value)
{
return decrypt($value);
}
public function setEmailAttribute($value)
{
$this->attributes['email'] = encrypt($value);
}
So you will have email encrypted in the database and you can use $user->email in your code.
But I have to warn you that with encrypted email the login process is irreparably broken, you have to use another unique field like username for the login, not the email, so in your login controller you have to write:
public function username()
{
return 'username';
}

Spring Securty - How to share bcrypt between two applications?

I have a REST api application where the credentials are stored as hashes in a database table. Additionally I have another application which administrates the credentials for the first application. I generated in both application an DelagtingPasswordEncoder.
#Bean
public PasswordEncoder delegatingPasswordEncoder() {
PasswordEncoder defaultEncoder = NoOpPasswordEncoder.getInstance();
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("bcrypt", new BCryptPasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder("bcrypt", encoders);
passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);
return passworEncoder;
}
When I try to authenicate at the REST api with a credential generated by the administration application I get an Unauthorized 401. The bcrypt hash generated in the administrator application could not be matched by the bcrypt of the REST api application. I assume the random salt generated by bcrypt is also dependent on the context it is initialized in?
We used Basic Auth for the test, with the correct password generated by the administration appliction before storing it as a hash in the database.
Both applications share the same database, but are otherwise independent from each other.
Is it possible to use bcrypt in both applications or what is the best way to exchange the passwords between both applications?
You don't need to share the BCrypt encoder between applications.
The structure of the BCryptPasswordEncoder hash is a concatenation of:
hashing algorithm
number of hash iterations
salt
hashed salt + password
When you do an authentication, you basically get a username and a password from the user request, fetch the user based on the provided username from the database, extract the hashing algorithm, number of iterations and salt from the hashed password from the database, hash the request password based on that data and then compare the hashes. There is no salt generation involved when you authenticate a user. Salt is generated only when you create or update a password.
Note that the hashing algorithm, number of iterations and salt extraction is done behind the hood by the matches method from BCryptPasswordEncoder (which takes as arguments the hashed password and the plain password).
My best guess is that you are not using the matches method from BCryptPasswordEncoder to compare the request password with the DB password, but rehash the request password and compare the resulted hash with the db hash. This won't work, since the encoded method will generate a new salt with which will hash the password, resulting in different hashes.

Password encoding and decoding using Spring Security, Spring Boot and MongoDB

I use the mentions software stack above and I need to encrypt password before save into database. I also need to decrypt password because when someone will change password he she needs to give in the old password and then the new onw twice and I need to check the old password.
I have searched a lot but I still not sure what is the right way to do this.
I have found this link Encrypting but are there other hints to do this?
I also not sure if maybe MongoDB provides something to protect passwords.
First read Steven CarlsonĀ“s answer about password hashing.
The good thing is that Spring Security will do this for you. Spring Security 3.2 introduced the new org.springframework.security.crypto.password.PasswordEncoder interface and some implementations: BCryptPasswordEncoder, StandardPasswordEncoder (and NoOpPasswordEncoder).
Important: Do not confuse org.springframework.security.crypto.password.PasswordEncoder with the old deprecated org.springframework.security.authentication.encoding.PasswordEncoder
The interface (and therefore the implementations) has the two methods you need:
public String encode(CharSequence rawPassword)
public boolean matches(CharSequence rawPassword, String encodedPassword)
I recommend to use org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.
The BCryptPasswordEncoder (in contrast to the StandardPasswordEncoder) use an salt that is different for each password (but not global like the one from StandardPasswordEncoder). When you encode a raw password (public String encode(CharSequence rawPassword)) then the returned encoded password is not just the encoded password, it also contains some meta information about the used hash-algorithm, the used salt and of course the encoded password.
You should not be "encrypting" the password at all. I know this sounds counter-intuitive. But there is zero reason your system should need to decrypt the password. To do so would open your database to a hacker, because if you store your decryption password in your codes/server a hacker can steal that information.
The correct process is to hash the password. A hash is a one-way (cannot be decypted back to the original text) process. The current standard would be to use SHA256 to hash your password. Here is a basic flow-chart:
Take user submitted password. Example password "mypass" would hash out to ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
Store this hash (ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222) in your database.
When a user logs in you take the password he just submitted and hash it. If he enters the same password it will hash out to the same value in your database.
When a user goes to change passwords you hash the "enter your old password" to verify the old password still matches, if it does you hash the "enter your new password" and save it.
One thing I did not mention in my example is salt. This is something you must use in your system as it protects your data from rainbow table exploits. But that is for another discussion.
Hope this helps :)

Resources