Question

I had to migrate a legacy database with clear text password to a PostgresSQL database. I've looked up what's the best way to encrypt password in a database and found the pgcrypto extension with slow algorithm. (see pgcrypto documentation for 8.4)

The migration is done for data and everything is working well. Now I have to write a CRUD application to handle this data. I'm wondering what's the best way to use this strong encryption with grails ?

In my model, I've used the afterInsert event to handle this :

def afterInsert() { 
    Compte.executeUpdate("update Compte set hashpass=crypt(hashpass, gen_salt('bf', 8)) where id = (:compteId)", [compteId: this.id])
}

I guess that I should also check if the hashpass field is modified whenever the model is saved. But before that, is there another (best) way to achieve my goal ?

Edit : I cannot use the Spring Security bcrypt plugin here. The CRUD application that I'm writing use SSO CAS so I don't need such a plugin. The CRUD application manages accounts for another application that I don't own. I just need to create a new account, modify or delete an existing one. This is very simple. The tricky part is to hack grails so that it takes into account the password field and use a specific sql to store it to a postgreSQL database.

Edit 2 :

I've come up with the following code but it doesn't work

def beforeInsert() {
    hashpass = encodePassword(hashpass);
}

def encodePassword(cleartextpwd) {
    // create a key generator based upon the Blowfish cipher
    KeyGenerator keygenerator = KeyGenerator.getInstance("Blowfish");

    // create a key
    SecretKey secretkey = keygenerator.generateKey();

    // create a cipher based upon Blowfish
    Cipher cipher = Cipher.getInstance(ALGORITHM);

    // initialise cipher to with secret key
    cipher.init(Cipher.ENCRYPT_MODE, secretkey);

    // get the text to encrypt
    String inputText = cleartextpwd;

    // encrypt message
    byte[] encrypted = cipher.doFinal(inputText.getBytes("UTF-8"));
    return Base64.encodeBase64String(encrypted);
}

I get a hash that is not a blowfish hash (beginning with $2a$08$ )

Edit 3 :

I've finally came up with a cleaner grails solution after reading this wiki page : grails.org/Simple+Dynamic+Password+Codec (not enough reputation to put more than 2 links so add http:// before) and the bug report jira.grails.org/browse/GRAILS-3620

Following advice from @lukelazarovic, I've also used the algorithm from the spring security plugin.

Here is my password encoder to put into grails/utils :

import grails.plugin.springsecurity.authentication.encoding.BCryptPasswordEncoder;

class BlowfishCodec {

static encode(target) {
            // TODO need to put the logcount = 8 in configuration file
    return new BCryptPasswordEncoder(8).encodePassword(
        target, null)
}
}

I've updated my Compte model to call my password encoder before saving / updating the data :

def beforeInsert() {
    hashpass = hashpass.encodeAsBlowfish();
}

def beforeUpdate() {
    if(isDirty('hashpass')) {
            hashpass = hashpass.encodeAsBlowfish();
    }
}
Was it helpful?

Solution

The tricky part is to hack grails so that it takes into account the password field and use a specific sql to store it to a postgreSQL database.

Is there any particular reason to do the hashing in database?

IMHO it's better to hash the password in Grails, therefore have a code that is not database-specific and easier to read.

For hashing passwords using Blowfish algorithm using Java or Groovy see Encryption with BlowFish in Java

The resulting hash begins with algorithm specification, iteration count and salt, separated with dollar sign - '$'. So the hash may look like "$2a$08$saltCharacters" where 2a is a algorithm, 08 is iteration count, then follows salt and after salt is the hash itself.

For broader explanation see http://www.techrepublic.com/blog/australian-technology/securing-passwords-with-blowfish. Don't mind that it concerns to Blowfish in PHP, the principles applies for Java or Groovy as well.

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