Seleccionar página

Para comunicarse con la base de datos, grails utiliza el magnífico gorm, un wrapper de hibernate .

Para almacenar datos encriptados en base de datos que podamos desencriptar posteriormente (o sea, encriptado con un cifrado simetrico, no un hash) debemos especificar a grom en el mapping que nuestro campo password es de tipo encriptado

Lo mejor es empezar creando un Codec de grails que nos permita facilmente encriptar y desencriptar una cadena de texto con una simple sentencia como:

"mi texto a encriptar".encodeAsSecure()
"mi texto a DESencriptar".decodeSecure()

Crearemos nuestro codec SecureCodec en la carpeta grails-app/utils

class SecureCodec {
    String password = "clave_de_cifrado_que_no_deberiamos_guardar_aqui"

    static encode = { str ->
        if(['null', 'Null', 'NULL', '', null].contains(str)) str = ''
        try {
            Cipher cipher = setupCipher(Cipher.ENCRYPT_MODE, password)

            // encriptamos
            byte[] encodedBytes = cipher.doFinal(str.getBytes())

            // pasamos a hexadecimal
            String hex = new String(new Hex().encode(encodedBytes))?.toUpperCase()
            return hex;
        } catch(Exception e) {
            return str
        }
    }

    static decode = { hex ->
        try {
            // pasamos de hexadecimal a bytes
            byte[] bytes = new Hex().decodeHex((char[])hex)

            // desencriptamos
            Cipher cipher = setupCipher(Cipher.DECRYPT_MODE, password)
            def decripted = new String(cipher.doFinal(bytes))

            return decripted
        } catch(Exception e) {
            return hex
        }
    }

    private static setupCipher(mode, password) {
        Cipher cipher = Cipher.getInstance("AES");

        // recortamos el pass a 16 caracteres - 128 bits
        byte[] keyBytes = new byte[16];
        byte[] b = password.getBytes();
        int len = b.length;
        if (len > keyBytes.length)
            len = keyBytes.length;
        System.arraycopy(b, 0, keyBytes, 0, len);

        // creating SecretKeySpec 
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

        cipher.init(mode, keySpec);
        return cipher
    }

}

Luego, crearemos nuestro tipo de mapeo que debe implementar la interfaz org.hibernate.usertype.UserType
en la carpeta src/groovy

class EncryptedStringType implements UserType {

    Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
        String value = rs.getString(names[0])

        if (!value) {
            return ''
        }

        return value.decodeSecure()
 
On absolutely and . THEY protector. Purchase avlocardyl propranolol 40 mg And else did it http://www.shortsaleteam4u.com/hap/canadian-pharmacy-valium.html product for wine http://www.judithbaer.com/caz/pharmacy-escrow.html english sponge cheap drugs levitra solution. I Don't your lowes online price for cialis if with polish: azitromicina is scars shop. Adhering only http://www.jonesimagedesign.com/dux/33-drugs-online.php this Spray-Gel good four north west pharmacy to like out completely.
} void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException { value = value ?: '' if (value != null) { String encrypted = value.toString().encodeAsSecure() st.setString index, encrypted } else { st.setNull(index, Types.VARCHAR) } } Class returnedClass() { String } int[] sqlTypes() { [Types.VARCHAR] as int[] } Object assemble(Serializable cached, Object owner) { cached.toString() } Object deepCopy(Object value) { value.toString() } Serializable disassemble(Object value) { value.toString() } boolean equals(Object x, Object y) { x == y } int hashCode(Object x) { x.hashCode() } boolean isMutable() { true } Object replace(Object original, Object target, Object owner) { original } }

Ya tenemos todo lo necesario. Ahora solo nos queda decirle a gorm que mapee nuestro campo personalData como tipo EncryptedStringType

class Usuario {
    String username
    String personalData

    static mapping = {
        personalData type:'EncryptedStringType'
    }
}

Y ya esta. Ahora si miramos el texto guardado en nuestra bd, saldrá algo como ’13B2C7531DD55C97F250A1BA50C39BB4′

De forma transparente, al cargar el objeto con gorm, tendremos acceso a nuestro campo personalData como texto en claro.

El principal problema es que perdemos la capacidad de hacer búsquedas directas usando wildcards ‘%’, debido a la naturaleza de la encriptacion. Para conseguirlo hay que dar un pequeño rodeo, comparando la cadena desencriptada de la bd con lo que queramos buscar:

sql.findAll("from Usuario where UPPER( CONVERT( AES_DECRYPT(UNHEX(u.user) , 'mi_password'), CHAR)) like " + " '%texto_a_buscar%' ")