Hibernate Encryption of Database Completely Transparent to Application

前端 未结 7 1002
春和景丽
春和景丽 2021-02-03 12:59

I\'m working on a Grails 1.0.4 project that has to be released in less than 2 weeks, and the customer just came up with a requirement that all data in the database should be enc

7条回答
  •  借酒劲吻你
    2021-02-03 13:42

    If you end doing the work in the application, you can use Hibernate custom types and it wouldn't add that many changes to your code.

    Here's an encrypted string custom type that I've used:

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

    and based on this it should be simple to create similar classes for int, long, etc. To use it, add the type to the mapping closure:

    class MyDomainClass {
    
      String name
      String otherField
    
      static mapping = {
        name type: EncryptedString
        otherField type: EncryptedString
      }
    }
    

    I omitted the CryptoUtils.encrypt() and CryptoUtils.decrypt() methods since that's not Grails-specific. We're using AES, e.g. "Cipher cipher = Cipher.getInstance('AES/CBC/PKCS5Padding')". Whatever you end up using, make sure it's a 2-way crypto, i.e. don't use SHA-256.

提交回复
热议问题