Расшифровать зашифрованные значения Laravel

#php #mysql #laravel #encryption

#php #mysql #laravel #шифрование

Вопрос:

У меня есть приложение Laravel, которое использует шифрование и дешифрование с помощью функции шифрования Laravel по умолчанию.

Теперь мне нужно перенести базу данных в другую.

Я создал SQL-скрипт, который обрабатывает миграцию данных, но во время миграции мне нужно выполнить некоторые проверки в некоторых полях. Например:

 insert into test.table
            (valueA, valueB, valueC) 
SELECT      tb.a, tb.b, tc.c
from        db2.tableB tb
join        test.tableC tc on tb.id = tc.tb_id;

UPDATE      test.table
SET         valueD =  CASE  
            WHEN valueA = 'example' THEN 1 
            ELSE 0
END;
  

Проблема в том, что некоторые из этих полей зашифрованы.
Например, ValueA будет выглядеть примерно так:

eyJpdiI6ImtTTUthN0dFT2N3Qkt6REdaamIyWGc9PSIsInZhbHVlIjoiakFIa0RFTVdCSU1LM1hWY3NUM0tVUT09IiwibWFjIjoiOGI1ZjY5ODVkYzMwYTIxMTExMzgyNjZmMTViNDllZTUzYWUxNzEyMWEwNmM5M2RmZDQzNzcwMDY4MjlkYzVlOCJ9

Я пытался использовать AES_DECRYPT(), используя APP_KEY, который у меня есть в Laravel, но скрипты всегда возвращают null. Например:

 SELECT AES_DECRYPT(from_base64(valueA),'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') from 
test.table;
  

Всегда возвращает значение NULL.

Очевидно, что ключ скрыт для целей этого сообщения.

Я думаю, что это связано с тем, что Laravel использует open_ssl при шифровании, в то время как AES_DECRYPT этого не делает. Я прав?

Есть ли способ расшифровать базу данных перед запуском моего сценария миграции или расшифровать значение в инструкции SELECT во время обновления?


Обновить:

Я настроил MySQL для использования «AES-256-CBC». Имейте в виду, что в Laravel APP_KEY выглядит примерно так: «base64: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx»

Итак, это то, что я делаю сейчас:

 SET block_encryption_mode = 'aes-256-cbc';
SET @key_str = to_base64('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
SET @init_vector = (SELECT LEFT(CONVERT(encryptedVal USING binary), 16)  from tableA where id =1);
SELECT encryptedVal, AES_DECRYPT(encryptedVal,@key_str,@init_vector) from tableA where id = 1;
  

Кстати, у меня все еще есть нулевые значения.
Любая помощь будет оценена

Комментарии:

1. Я нашел указание на то, что Laravel использует AES HMAC для целостности / аутентификации, но пока нет спецификации, как будто они не хотят, чтобы вы специально ее находили. Вероятно, он использует это .

2. Привет @MaartenBodewes. Да, он использует связанную вами черту. Основываясь на том, что вы там прочитали, знаете ли вы, как (если) я могу расшифровать непосредственно в MySQL Workbench?

3. Я немного запутался, либо это IV CBC(plaintext) , либо это IV CBC(plaintext) MAC . Если посмотреть AES_DECRYPT , по умолчанию используется режим ECB с использованием системной переменной, и он включает IV в параметры, а не в зашифрованный текст. Как и большинство функций шифрования БД, это невероятно глупо; относительно небольшое шифрование базы данных, похоже, разработано экспертами. Но да, измените режим на CBC, извлеките IV из зашифрованного текста (первые 16 байт), а затем расшифруйте. Если это не работает, это, вероятно, из-за того, что MAC все еще присутствует.

4. Еще раз спасибо за ваш ответ @MaartenBodewes. Я пытался изменить режим на CBC в MySQL с SET block_encryption_mode = 'aes-256-cbc помощью . Кстати, я получаю следующую ошибку: Error Code: 1193. Unknown system variable 'block_encryption_mode' . Для меня это звучит действительно странно, потому что, если я запускаю SHOW VARIABLES LIKE "%version%"; , я получаю 'version', '10.4.11-MariaDB' , что block_encryption_mode должен присутствовать в той версии, которая у меня есть. Есть идеи, почему это происходит?

5. Нет, возможно, задайте отдельный вопрос об этом после поиска. SET block_encryption_mode = 'aes-256-cbc'; буквально, кажется, присутствует в документации. Я пытался держаться подальше от программирования БД, я больше эксперт по безопасности.

Ответ №1:

Если кому-то нужно, я закончил созданием скрипта, вызываемого из Laravel, который расшифровывает нужные мне таблицы и поля:

 class DecryptDatabase extends Command
{
    protected $tables = (array(
        "tableA" => array(
           "pk" => 'id',
           "encrypted" =>  array('valueA', 'valueB', 'valueC'),
           "name" => "tableA"
           ),
        "users" => array(
            "pk" => 'id',
            "encrypted" =>  array('name', 'surname', 'profession'),
            "name" => "users"
            ),
        ));

    public function handle()
    {
        foreach($this->tables as $t) {
            $columns = implode(',', $t['encrypted']);
            $q = DB::connection('mysql2')->select('select ' . $t['pk']. ','. $columns . ' from '. $t['name']);
            foreach($q as $result)
            {
                $pk = $t['pk'];
                try {
                    foreach($t['encrypted'] as $enc) {
                        if($result->$enc != null){
                            $decrypted = Crypt::decrypt($result->$enc);
                            $query = DB::connection('mysql3')
                            ->table($t['name'])
                            ->where($t['pk'], $result->$pk)
                            ->update([$enc => $decrypted]);
                        }
                    }
                } catch (DecryptException $e) {
                    echo ("Error in decryption: ". $e);
                }
            }
        }  
        echo "Decryption terminated";
        return 0;
    }
}
  

Этот скрипт расшифровывает все поля, определенные в переменной $tables.
Он использует базу данных, определенную в соединении «mysql2», в качестве источника зашифрованных значений, а затем сохраняет расшифрованные значения в базе данных, определенной в соединении «mysql3».

Первая база данных является исходной, а вторая — точной копией первой. Я сделал это для того, чтобы сохранить исходную базу данных нетронутой во время дешифрования, чтобы предотвратить повреждение данных в случае какой-либо ошибки во время дешифрования.

После расшифровки БД я могу правильно запустить свой сценарий миграции, а затем снова зашифровать БД, выполнив обратную функцию дешифрования.