I have a use case in my application that should prevent the user from choosing one of their last 3 passwords while resetting their password. I'm using Angular for the front end and Spring Boot for the back end . In my scenario, the user passwords are stored as bcrypt hash.
How can I compare the password entered by the user with the last 3 stored bcrypt passwords?
When I run the following code snipped example,
BCryptPasswordEncoder b = new BCryptPasswordEncoder();
for(int i =0;i<10;i++) {
System.out.println(b.encode("passw0rd"));
}
it generates the following bcrypt hashes. each hash is different which is reasonable because when I check the org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
, I can see the salt generated is random value.
$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm
$2a$10$yTHyWDmcCBq3OSPOxjj4TuW9qXYE31CU.fFlWxppii9AizL0lKMzO
$2a$10$Z6aVwg.FNq/2I4zmDjDOceT9ha0Ur/UKsCfdADLvNHiZpR7Sz53fC
$2a$10$yKDVeOUvfTQuTnCHGJp.LeURFcXK6JcHB6lrSgoX1pRjxXDoc8up.
$2a$10$ZuAL06GS7shHz.U/ywb2iuhv2Spubl7Xo4NZ7QOYw3cHWK7/7ZKcC
$2a$10$4T37YehBTmPWuN9j.ga2XeF9GHy6EWDhQS5Uc9bHvJTK8.xIm1coS
$2a$10$o/zxjGkArT7YdDkrk5Qer.oJbZAYpJW39iWAWFqbOhpTf3FmyfWRC
$2a$10$eo7yuuE2f7XqJL8Wjyz.F.xj78ltWuMS1P0O/I6X7iNPwdsWMVzu6
$2a$10$3ErH2GtZpYJGg1BhfgcO/uOt/L2wYg4RoO8.fNRam458WWdymdQLW
$2a$10$IksOJvL/a0ebl4R2/nbMQ.XmjNARIzNo8.aLXiTFs1Pxd06SsnOWa
Spring security configuration.
@Configuration
@Import(SecurityProblemSupport.class)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@PostConstruct
public void init() {
try {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
} catch (Exception e) {
throw new BeanInitializationException("Security configuration failed", e);
}
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Check A User Entered Password const bcrypt = require("bcryptjs") const passwordEnteredByUser = "mypass123" const hash = "YOUR_HASH_STRING" bcrypt. compare(passwordEnteredByUser, hash, function(err, isMatch) { if (err) { throw err } else if (! isMatch) { console. log("Password doesn't match!") } else { console.
You can't. BCrypt is a one way function. You can run bcrypt("password") twice and both times you will get different results, and there is no way of knowing that the two hashes are for the same password. This is a security feature, not a bug.
The compare function simply pulls the salt out of the hash and then uses it to hash the password and perform the comparison. When a user will log into our system, we should check the password entered is correct or not.
you can use matches
method in BCryptPasswordEncoder, something like this:
b.matches("passw0rd", hash)
Actually I found my answer .
I realized that I can use matches
function in the class org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.
System.out.println(b.matches("passw0rd", "$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm"));
Spring Security just reads the salt from previously generated hash and rehashes the input password again with same salt. And it compares both final hashes and obviously it will be same.
Example:
Password: test
Hash: $2a$10$nCgoWdqJwQs9prt7X5a/2eWLn88I8pon6iNat90u4rq4mHqtoPGQy
Hash has 3 segments each separated by $
symbol. 2a
is version of the Bcrypt, 10
is the total rounds and nCgoWdqJwQs9prt7X5a/2e
is the salt.
So spring security takes the password test
and salt nCgoWdqJwQs9prt7X5a/2e
and runs the hashing method. Obviously it generates the same hash as the password and salt matches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With