Spring security 3.1.4 and ShaPasswordEncoder deprecation

If you want to switch to a more secure password encoding mechanism, then I would recommend you use BCrypt. I would use something like this to migrate your users:

// Implement the old PasswordEncoder interface
public class MigrateUsersPasswordEncoder implements PasswordEncoder {
    @Autowired
    ShaPasswordEncoder legacyEncoder;
    @Autowired
    JdbcTemplate template;

    BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();

    @Override
    public String encodePassword(String rawPass, Object salt) {
        return bcryptEncoder.encode(rawPass);
    }

    @Override
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
        if (legacyEncoder.isPasswordValid(encPass, rawPass, salt)) {
            template.update("update users set password = ? where password = ?", bcryptEncoder.encode(rawPass), encPass);
            return true;
        }
        return bcryptEncoder.matches(rawPass, encPass);
    }
}

You can check what proportion of users have been migrated by the format of the password field. BCrypt strings have a distinctive syntax beginning with a $ sign.

One of the other answers points out that this code could accidentally update multiple passwords at the same time. The question stated that a custom salt was being used, so the chance of collisions is negligible if the salt is randomly chosen, but this might not always be the case. If two passwords were updated, what would the problem be? It would then be possible to detect that accounts have the same password from the bcrypt hashes. That’s the case anyway since it requires that the SHA hashes were the same for the update to occur. If you think it might be a problem (e.g. because of poor salt choice or even the use of unsalted hashes) it would be trivial to modify the SQL to detect this and perform multiple updates with separate BCrypt hash values.

Leave a Comment