Last Updated: February 25, 2016
·
1.554K
· morungos

Using bcrypt with Shiro

Yes, I know Shiro is supposed to be just fine for security with SHA256 and multiple iterations, but there's really no good excuse for it not supporting bcrypt. Anyway, I had a legacy app which stored many passwords in bcrypt, which I couldn't (obviously) read or port to SHA, so I really needed bcrypt. Fortunately, it was more or less trivial to plug in my own PasswordMatcher:

package ca.uhnresearch.pughlab.tracker.security;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.mindrot.jbcrypt.BCrypt;

public class BcryptPasswordMatcher implements CredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        String password = new String(userToken.getPassword());
        char[] credentials = (char[]) info.getCredentials();
        String hashed = new String(credentials);
        return BCrypt.checkpw(password, hashed);
    }

}

This injects fine into the credentialsMatcher property of, e.g., JdbcRealm.

Now I can just move over the database with hashes and all existing users remain happy.