Шифрование определенных столбцов в Hibernate: что делать с существующими данными и как правильно реализовать @ColumnTransformer? - PullRequest
1 голос
/ 21 марта 2019

Я создал веб-приложение с базой данных MySQL, в котором хранятся данные пациентов. Согласно 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 я должен использовать?

1 Ответ

2 голосов
/ 21 марта 2019

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. Переименовать существующеестолбцы с использованием MySQLcommand:

    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')"
) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...