我已经建立了一个带有MySQL数据库的Web应用程序,其中包含患者数据。根据 GDPR 患者的姓名,必须在数据库内部对其进行加密。为了连接数据库并对其执行操作,我使用了Hibernate 5。

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

  • 使用@ColumnTransformer注释 hibernate ,对现有代码的破坏最小,并且需要编写的代码最少
  • 使用Jasypt及其Hibernate集成对现有代码更具破坏性,并且需要几行代码。
  • 实现一个JPA属性转换器,需要写很多行

  • 我决定使用@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代码?

    最佳答案

    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
    

    解决方案是:
  • 使用MySQL命令重命名现有列:
    ALTER TABLE Patient CHANGE firstName firstName-old;
    
    ALTER TABLE Patient CHANGE lastName lastName-old;
    
  • 使用命令创建两个新的mysqlt_code类型的MySQL列:
    ALTER TABLE Patient ADD COLUMN lastName VARBINARY(512) NOT NULL;
    
    ALTER TABLE Patient ADD COLUMN firstName VARBINARY(512) NOT NULL;
    
  • 使用以下命令从旧列更新新列:
    UPDATE `gourvas_platform`.`Patient` SET firstName=aes_encrypt(`firstName-old`, "my secret"), lastName=aes_encrypt(`lastName-old`, "mysecret");
    
  • 现在我们可以安全地删除旧列
  • 最后使用以下Hibernate varbinary(512)批注:
    @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函数返回@ColumnTransformer而不是binary[],所以我需要将String转换为文本。因此,上面的cast需要更改为以下内容:
    @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')"
    )
    

    09-26 21:27
    查看更多