首页 > 解决方案 > 在 Hibernate 中加密特定列:如何处理现有数据以及如何正确实现 @ColumnTransformer?

问题描述

我已经使用 MySQL 数据库构建了一个 Web 应用程序,该数据库包含患者数据。根据GDPR ,患者姓名必须在数据库内加密。为了连接和执行对 db 的操作,我使用 Hibernate 5。

在网上搜索,我发现了很多关于如何加密 db 表中的特定列或列的信息。主要有以下三种方法:

我决定使用@ColumnTransformer这似乎是最简单的实现。如果您认为其他方法之一更好,请说出来并解释原因。

然而,我的问题与现有数据有关。我的数据库已经有未加密的数据,必须对其进行加密才能与@ColumnTransformer实现一起使用。我打算使用以下注释:

@ColumnTransformer(
    read = "pgp_sym_decrypt(lastName, 'mySecretKey')", 
    write = "pgp_sym_encrypt(?, 'mySecretKey')"
)

@ColumnTransformer(
    read = "pgp_sym_decrypt(firstName, 'mySecretKey')", 
    write = "pgp_sym_encrypt(?, 'mySecretKey')"
)

到相应的列。

我应该如何加密现有数据以符合上述注释?我应该使用什么 SQL 代码?

标签: javamysqlsqlhibernate

解决方案


MySQL 支持以下功能:

  • AES_ENCRYPT(str, key_str);
  • AES_DECRYPT(crypt_str,key_str);

但是,我无法使用以下内容更新所有 MySQL 条目(因为 aes_encrypt 返回二进制文件):

UPDATE Patient SET firstName=AES_ENCRYPT(firstName, "mySecretKey"), lastName=AES_ENCRYPT(lastName, "mySecretKey") //NOT WORKING

解决方案是:

  1. 使用 MySQL 命令重命名现有列:

    ALTER TABLE Patient CHANGE firstName firstName-old;
    
    ALTER TABLE Patient CHANGE lastName lastName-old;
    
  2. 使用命令创建两个新的 MySQL 列varbinary(512)

    ALTER TABLE Patient ADD COLUMN lastName VARBINARY(512) NOT NULL;
    
    ALTER TABLE Patient ADD COLUMN firstName VARBINARY(512) NOT NULL;
    
  3. 使用以下命令从旧列更新新列:

    UPDATE `gourvas_platform`.`Patient` SET firstName=aes_encrypt(`firstName-old`, "my secret"), lastName=aes_encrypt(`lastName-old`, "mysecret");
    
  4. 现在我们可以安全地删除旧列

  5. 最后使用以下 Hibernate@ColumnTransformer注解:

    @ColumnTransformer(
        read = "AES_DECRYPT(lastName, 'mySecretKey')", 
        write = "AES_ENCRYPT(?, 'mySecretKey')"
    )  
    

    @ColumnTransformer(
        read = "AES_DECRYPT(firstName, 'mySecretKey')", 
        write = "AES_ENCRYPT(?, 'mySecretKey')"
    )  
    

注意:因为我使用的是 MySQL 5.7 并且 AES_DECRYPT 函数返回binary[]而不是String,所以我需要输入cast文本。所以上面@ColumnTransformer需要改成如下:

@ColumnTransformer(
read = "cast(aes_decrypt(lastName, 'my secret') as char(255))", 
write = "aes_encrypt(?, 'mysecret')"
) 

@ColumnTransformer(
read = "cast(aes_decrypt(firstName, 'myscret') as char(255))", 
write = "aes_encrypt(?, 'mysecret')"
) 

推荐阅读