Question

I'm trying to use the BCrypt password hashing in my Grails app that's using the Spring Security plugin. I've enabled BCrypt by adding the following to Config.groovy

grails.plugins.springsecurity.password.algorithm = 'bcrypt'

And I've defined the following codec to simplify using BCrypt to encode paswords:

public class PasswordCodec {

    // it doesn't seem to be possible to dependency-inject codecs, so lookup the bean ourselves
    @Lazy
    private static PasswordEncoder passwordEncoder = Holders.grailsApplication.mainContext.getBean('passwordEncoder')

    static encode = { str ->
        passwordEncoder.encodePassword(str.toString(), null)
    }
}

When I start the application in dev mode the database is bootstrapped with a few accounts (each of which has the same password, e.g.

3.times { i ->
    def username = "user$i"
    def password = "secret".encodeAsPassword()

    new User(username: username, password: password).save()
    // also assign the user a role
}

If I look in the database, I see that the encoded value of each of these user's password is different! So it's no surprise that when a user attempts to login and enters a password of "secret", the BCrypt-encoded password value doesn't match what's saved in the database, because it seems that the BCrypt-encoded value of a String somehow changes over time.

Obviously I'm doing something wrong here, but I've no idea what?

Was it helpful?

Solution

Often password hashes are identical given the same input (and very occasionally with different inputs). But bcrypt and others generate a different hash each time. This isn't a problem however, because the PasswordEncoder interface has both the String encodePassword(String rawPass, Object salt) method to generate hashes, but also the boolean isPasswordValid(String encPass, String rawPass, Object salt) method to validate them.

With simpler hashes like MD5, SHA-1, etc. the process for verification is simply re-encoding the cleartext password and checking that it's the same as the stored hashed value. The process is a lot more complicated with bcrypt, but the end result is the same - it doesn't check for equality, but instead that they're equivalent. So if you hash the same password twice and compare them with isPasswordValid it will return true.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top