Mysql
 sql >> Base de données >  >> RDS >> Mysql

Cryptage Hibernate de la base de données complètement transparent pour l'application

Si vous finissez de travailler dans l'application, vous pouvez utiliser les types personnalisés Hibernate et cela n'ajoutera pas autant de modifications à votre code.

Voici un type personnalisé de chaîne chiffrée que j'ai utilisé :

import org.hibernate.usertype.UserType
import org.apache.log4j.Logger

import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types

class EncryptedString implements UserType {

  // prefix category name with 'org.hibernate.type' to make logging of all types easier
  private final Logger _log = Logger.getLogger('org.hibernate.type.com.yourcompany.EncryptedString')

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

    if (!value) {
      _log.trace "returning null as column: $names[0]"
      return null
    }

    _log.trace "returning '$value' as column: $names[0]"
    return CryptoUtils.decrypt(value)
  }

  void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
    if (value) {
      String encrypted = CryptoUtils.encrypt(value.toString())
      _log.trace "binding '$encrypted' to parameter: $index"
      st.setString index, encrypted
    }
    else {
      _log.trace "binding null to parameter: $index"
      st.setNull(index, Types.VARCHAR)
    }
  }

  Class<String> 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 }
}

et sur cette base, il devrait être simple de créer des classes similaires pour int, long, etc. Pour l'utiliser, ajoutez le type à la fermeture de mappage :

class MyDomainClass {

  String name
  String otherField

  static mapping = {
    name type: EncryptedString
    otherField type: EncryptedString
  }
}

J'ai omis les méthodes CryptoUtils.encrypt() et CryptoUtils.decrypt() car ce n'est pas spécifique à Grails. Nous utilisons AES, par ex. "Cipher cipher =Cipher.getInstance('AES/CBC/PKCS5Padding')". Quoi que vous finissiez par utiliser, assurez-vous qu'il s'agit d'une cryptographie bidirectionnelle, c'est-à-dire n'utilisez pas SHA-256.