I use Spring security in this question but its knowledge might not be required to answer this question.
I am trying to understand how Spring security's blowfish encryption class (BCrypt
) verifies a given password. I tried to :
- Generate a Salt with
BCrypt.gensalt(10);
- Encode a password using this salt with
BCrypt.hashpw(clearText, salt)
.
It worked well.Then, I wanted to store the used salt in the database in order to be able to reuse it when the users enter a password.
I realized that BCryptPasswordEncoder
does not use the salt when it checks the password. Instead, it crypts the password with its hashed password as salt :
public boolean matches(CharSequence rawPassword, String encodedPassword) {
[...]
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
}
So I tried this piece of code :
public static void main(String[] args) {
String salt = BCrypt.gensalt(12);
String clearText="test";
String hashed = BCrypt.hashpw(clearText, salt);
String reHashed = BCrypt.hashpw(clearText, hashed);
System.out.println("salt : " + salt);
System.out.println(hashed);
System.out.println(reHashed);
}
output :
salt : $2a$12$gzUymsNBoW.f1OfkLpb2se
$2a$12$gzUymsNBoW.f1OfkLpb2seFZrniorawujSOp6Qe.PWDIHJvmYSP6y
$2a$12$gzUymsNBoW.f1OfkLpb2seFZrniorawujSOp6Qe.PWDIHJvmYSP6y
This seems to confirm that :
good password => hashed = hash(clearPassword, hashed)
Am I understanding it wrong? Does it mean that the salt is useless for password checking? Hence, does it mean that I do not need to store the salt in database?
BCrypt stores the salt as part of the "hash" string that it returns.
This is handled by the
Bcrypt.*
functions, so you don't need to do anything.