Today I upgraded the spring security version of the application I'm working on from 3.1.3 to 3.1.4, and I noticed a deprecation warning on the org.springframework.security.authentication.encoding.ShaPasswordEncoder
class.
So I switched to the new org.springframework.security.crypto.password.StandardPasswordEncoder
implementation.
I had it working and I'm able to register a new user and login in my application, but, as I feared, I'm not able to login using passwords generated with the previous ShaPasswordEncoder and my custom salt.
Since I have a database with many users already registered, what should I do to switch implementation without invalidating the old encoded passwords? Is it even possible?
See also: How to use new PasswordEncoder from Spring Security
The UsernamePasswordAuthenticationToken is an implementation of interface Authentication which extends the interface Principal . Principal is defined in the JSE java. security . UsernamePasswordAuthenticationToken is a concept in Spring Security which implements the Principal interface.
Scrypt is based on Salsa20 which performs poorly in Java (on par with AES) but performs awesome (~4-5x faster) on SIMD capable platforms.
Generate a BCrypt PasswordThis example uses BCryptPasswordEncoder to hash a password “123456”. In BCrypt hashing algorithm, each time, a different hash value of length 60 is generated. It's normal to get a different value each time you hash a value with BCrypt, because salt is generated randomly.
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
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.
I tried to add a comment to the accepted answer, but alas, I don't have enough cred yet. :(
I believe the accepted answer's code snippet is potentially dangerous where it updates the password in the database. If the ShaPasswordEncoder produces the same results when encrypting (which is why the assumption is being made that the old password can be found, and I verified this is definitely true at least with a null salt on the ShaPasswordEncoder), you still cannot guarantee that the password is unique amongst all users. You could, by chance, share the same password as another user on the system, and that SQL code would end up changing all users that happen to have your password.
I think the safest strategy is to not update the user's password, and instead provide a migration strategy that plans for the eventual removal of the ShaPasswordEncoder.
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