Spring MVC- Authentication with or without salt

2019-09-05 14:56发布

问题:

My current method of registering and authenticating a User is as follows:

class User{

private String username;
private String password;
private String salt;
}

Registeration :

addUser(String username, String password){

user.setUsername(username);

user.setSalt(BCrypt.gensalt());

user.setPassword(BCrypt.hashpw(password, user.getSalt()));
}

Authentication :

authenticate(User user){

User userDB = getUserFromDB(user.getUsername());

userDB.getPassword().equals(BCrypt.hashpw(user.getPassword(), userDB.getSalt()))

}

However I am looking at Spring Boot authentication systems and I see people recommending using BCryptPasswordEncoder which only uses password and no salt.

I needed to know if my existing method is better or worse than the one being recommended.

回答1:

BCryptPasswordEncoder uses a salt. From the documentation:

public String encode(CharSequence rawPassword)

Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or greater hash combined with an 8-byte or greater randomly generated salt.

From the source:

public String encode(CharSequence rawPassword) {
    String salt;
    if (strength > 0) {
        if (random != null) {
            salt = BCrypt.gensalt(strength, random);
        }
        else {
            salt = BCrypt.gensalt(strength);
        }
    }
    else {
        salt = BCrypt.gensalt();
    }
    return BCrypt.hashpw(rawPassword.toString(), salt);
}

BCryptPasswordEncoder generates its own salt upon encoding. This is what the optional SecureRandom constructor argument is used for. The output of BCrypt includes the salt, which is how a raw password is verified. This is why the matches method requires the already encoded password.

Sample output from bcrypt "example":

$2y$10$Tqq.bRDh6N3JDNzn0oBd7OCFjsHyiuf39VMmZnrw9MWi.xtTiWtni

The output of bcrypt includes:

  • 2y indicates Blowfish cipher
  • 10 rounds (actually 2^10 rounds)
  • first 22 characters after third $ are the salt, remainder are the hash

PHP documentation describes bcrypt output:

Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".


Your method does the same thing, but you are storing the salt explicitly by itself. Instead of storing the salt separately, you can simply use the salt that is stored in the bcrypt output, as described in the method public static boolean checkpw(String plaintext, String hashed)