一尘不染

数据库的Hibernate加密对应用程序完全透明

hibernate

我正在一个Grails 1.0.4项目中工作,该项目必须在不到2周的时间内发布,并且客户刚提出一个要求,即应该加密数据库中的所有数据。

由于对应用程序本身中的每个数据库访问进行加密可能会花费大量时间,并且容易出错,因此我寻求的解决方案是对应用程序透明的某种加密。

有没有一种方法可以将Hibernate设置为加密所有表中的所有数据(可能不包括id和version列),还是应该寻求MySQL解决方案(我们使用的是MySQL
5.0)?

编辑:感谢您为替代解决方案提供的所有帖子,如果客户改变主意,那将是很好的。到目前为止,要求是“数据库中没有纯文本”。

我想指出的第二件事是,我正在使用Grails,对于那些不熟悉它的人,这是对配置的约定,因此即使对应用程序进行的较小更改也应避免约定。


阅读 303

收藏
2020-06-20

共1个答案

一尘不染

自从我问了这个问题以来已经有很长时间了。同时,感谢您的所有回答。当处理最初加密整个数据库的想法时,它们很棒,但是要求变为只加密敏感的用户信息,例如名称和地址。因此解决方案类似于下面的代码。

我们已经实现了一个加密器,该加密器从记录中读取加密方法(因此每个记录可以有不同的加密),并使用它来将瞬态重复字段与数据库中加密的字段连接起来。增加的红利/缺点是:

  • 数据也在内存中进行了加密,因此对方法getFirstName的每次访问都会解密数据(我想有一种缓存已解密数据的方法,但在这种情况下我不需要)
  • 加密的字段不能与默认的grails / hibernate方法一起使用来搜索数据库,我们已经在服务中创建了自定义方法来获取数据,对其进行加密,然后在查询的where子句中使用加密的数据。使用User.withCriteria时很容易

类用户{

    byte[] encryptedFirstName
byte[] encryptedLastName
byte[] encryptedAddress

Date dateCreated // automatically set date/time when created
Date lastUpdated // automatically set date/time when last updated

EncryptionMethod encryptionMethod = ConfigurationHolder.config.encryption.method

def encrypter = Util.encrypter

static transients = [ 
'firstName', 
'lastName', 
'address',
'encrypter'
]

static final Integer BLOB_SIZE = 1024

static constraints = {

    encryptedFirstName maxSize: BLOB_SIZE, nullable: false
    encryptedLastName maxSize: BLOB_SIZE, nullable: false

    encryptedAddress maxSize: BLOB_SIZE, nullable: true

    encryptionMethod nullable: false

} // constraints

String getFirstName(){
    decrypt('encryptedFirstName')
}

void setFirstName(String item){     
    encrypt('encryptedFirstName',item)
}

String getLastName(){
    decrypt('encryptedLastName')
}

void setLastName(String item){
    encrypt('encryptedLastName',item)       
}

String getAddress(){
    decrypt('encryptedAddress')
}

void setAddress(String item){
    encrypt('encryptedAddress',item)        
}

byte[] encrypt(String name, String value) {

    if( null == value ) {
        log.debug "null string to encrypt for '$name', returning null"
        this.@"$name" = null
        return
    }

    def bytes = value.getBytes(encrypter.ENCODING_CHARSET)
    def method = getEncryptionMethod()


    byte[] res

    try {
        res = encrypter.encrypt( bytes, method )            
    } catch(e) {
        log.warn "Problem encrypting '$name' data: '$string'", e
    }

    log.trace "Encrypting '$name' with '$method' -> '${res?.size()}' bytes"

    this.@"$name" = res

}

String decrypt(String name) {

    if(null == this.@"$name") {
        log.debug "null bytes to decrypt for '$name', returning null"
        return null
    }

    def res 
    def method = getEncryptionMethod()

    try {
        res = new String(encrypter.decrypt(this.@"$name", method), encrypter.ENCODING_CHARSET )
    } catch(e) {
        log.error "Problem decrypting '$name'", e
    }

    log.trace "Decrypting '$name' with '$method' -> '${res?.size()}' bytes"

    return res
}

}

2020-06-20