Как искать в базе данных MySQL с зашифрованными полями


15

Предположим, мне нужно зашифровать определенные поля таблицы в базе данных MySQL . Кроме того, мне нужно найти некоторые из тех полей, которые я зашифровал.

Как можно было бы искать эти поля в любом случае?

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

ОБНОВЛЕНИЕ 2012-09-07

Добавление дополнительных деталей в схему базы данных будет в порядке , так как я собираюсь реализовать новое приложение. Кроме того, мне нужно расширить приложения, работающие в настоящее время в производстве. Но даже для этих приложений добавление дополнительной информации будет в порядке.

ОБНОВЛЕНИЕ 2012-09-08

Шифрование является ядром этого вопроса.

Ограничения доступа, предложенные в некоторых ответах, уже применяются, но не соответствуют формальным требованиям для шифрования данных.

Это формальное требование не является стандартом безопасности данных индустрии платежных карт [PCI].

Ответы:


11

Очевидно, что они не предназначены для просмотра, поэтому поиск по ним будет проблематичным.

Один прием, который я использовал в прошлом, заключается в хешировании зашифрованных данных перед их шифрованием и сохранении хеша в индексированном столбце. Конечно, это работает, только если вы ищете по всей стоимости; частичные значения не будут иметь одинаковый хэш.

Возможно, вы могли бы расширить это, сделав «полнотекстовый» индекс хешей, если вам нужно, но это может очень быстро усложниться.

ДОПОЛНЕНИЕ

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

Атака по словарю. Атака по словарю - это когда кто-то предварительно хеширует список известных значений и сравнивает хэши с вашим хэшированным столбцом в базе данных. Если они могут найти совпадение, вероятно, известное значение на самом деле является тем, что хэшируется (хотя это не является определенным, потому что хэши не гарантированно будут уникальными). Обычно это смягчается хэшированием значения с добавлением или добавлением случайной «соли», чтобы хэш не совпадал со словарем, но в приведенном выше ответе нельзя использовать соль, поскольку вы теряете возможность поиска.

Эта атака опасна, когда речь идет о таких вещах, как пароли: если вы создаете словарь популярных хэшей паролей, вы можете быстро найти в таблице это значение хеш-функции и определить пользователя, у которого есть такой пароль, и эффективно извлечь учетные данные, чтобы украсть личность этого пользователя. ,

Это менее опасно для предметов с высокой степенью кардинальности, таких как SSN, номера кредитных карт, GUID и т. Д. (Но существуют разные риски [читай: юридические], связанные с их хранением, поэтому я не склонен советовать их хранить ).

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

Вы также можете найти конкретный номер SSN или номер кредитной карты, если вы пытаетесь сопоставить номер SSN с человеком. Опять же, обычно это не точка атаки по словарю, но это возможно сделать, поэтому, если вам нужно избежать этого риска, мой ответ не является хорошим решением для вас.

Так что у вас есть это. Как и для всех зашифрованных данных, они обычно зашифрованы по какой-либо причине, поэтому будьте внимательны с вашими данными и от того, от чего вы пытаетесь их защитить.


Обсуждение этого ответа было перенесено в чат .
Пол Уайт восстановил Монику

5

Возможно, вы захотите взглянуть на CryptDB . Это интерфейс для MySQL и PostgreSQL, который позволяет прозрачное хранение и запрос зашифрованных данных. Он работает путем шифрования и дешифрования данных при их передаче между приложением и базой данных, переписывая запросы для работы с зашифрованными данными. и путем динамической настройки режима шифрования каждого столбца, чтобы предоставлять только столько информации, сколько необходимо для запросов, используемых приложением.

Различные методы шифрования, используемые CryptDB, включают в себя:

  • RND , полностью безопасная схема шифрования IND-CPA, которая не дает никакой информации о данных (кроме их наличия и длины переменной длины), но позволяет только хранение и поиск, без запросов.

  • DET , вариант RND, который является детерминированным, так что два идентичных значения (в одном столбце) шифруются в один и тот же зашифрованный текст. Поддерживает запросы на равенство формы WHERE column = 'constant'.

  • OPE , схема шифрования с сохранением порядка, которая поддерживает запросы неравенства, такие как WHERE column > 'constant'.

  • HOM , частично гомоморфная схема шифрования (Paillier), которая позволяет складывать зашифрованные значения вместе, умножая шифротексты. Поддерживает SUM()запросы, дополнения и приращения.

  • ПОИСК , схема, которая поддерживает поиск по ключевым словам в форме WHERE column LIKE '% word %'.

  • JOIN и OPE-JOIN , варианты DET и OPE, которые позволяют сравнивать значения в разных столбцах. Поддерживать равенство и дальность соединения соответственно.

Реальная сила CryptDB заключается в том, что он динамически адаптирует метод шифрования каждого столбца к запросам, которые он видит, так что более медленные и / или менее безопасные схемы используются только для столбцов, которые в них нуждаются. Есть также различные другие полезные функции, такие как связывание ключей шифрования с паролями пользователей.

Если вам интересно, советуем взглянуть на статьи, ссылки на которые есть на сайте CryptDB, в частности на «CryptDB: Защита конфиденциальности с помощью шифрованной обработки запросов», выполненные Popa, Redfield, Zeldovich and Balakrishnan ( SOSP 2011 ). В этих документах также более подробно описываются различные компромиссы безопасности и производительности, связанные с поддержкой различных типов запросов.


1
It works by encrypting and decrypting data as it passes between the application and the databaseКонечно, это может вызвать проблемы, если искомые данные уже находятся в базе данных (зашифрованы), но очевидно, что сам запрос, выполняющий поиск в базе данных, только затем передается в CryptDB (а затем шифруется?). Я не могу понять, как этот метод может быть вообще эффективным?
Мартин

3

Я не понимаю, почему текущие ответы не подвергли сомнению требования полностью, поэтому я спрошу и оставлю это как ответ.

Каковы деловые причины? Какие данные вам нужно зашифровать и почему? Если вы ищете соответствие PCI, я мог бы написать эссе.

Вопросы о вашем требовании:

  • Вам нужно будет вернуть существующее / не существующее в результате или фактические данные?
  • Требуется ли вам возможность LIKE "% OMG_SEKRIT%"?
  • Кто не может видеть данные и почему?

Безопасность СУБД обычно осуществляется на основе разрешений, которые устанавливаются пользователем / ролью. Данные обычно шифруются СУБД на диске, но не в самих столбчатых данных, поскольку это не имеет никакого смысла для приложения, предназначенного для эффективного хранения и извлечения данных.

Ограничить по пользователю / роли / API. Зашифровать на диске. Если вы храните более важные данные, я хотел бы знать, почему вы используете MySQL.


Прежде всего, мне нужно найти существует / не существует, а затем найти конкретную запись. Полная LIKE поддержка будет в порядке. Но мне интересно, что будет возможно что-то большее, чем совпадение слов. Авторизованному пользователю разрешено просматривать данные. Приложение расшифровывает те элементы, которые имеет право просматривать законный пользователь. Схемы прав доступа не являются опцией.
SteAp

Каковы критерии для «более важных данных?»
арканин

2

Я смотрю на это и наткнулся на ваш вопрос. Я склоняюсь к подходу, изложенному в разделе 5.4 статьи «Практические методы поиска по зашифрованным данным» http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

Основная идея заключается в создании индекса, который содержит зашифрованные ключевые слова, которые присутствуют в зашифрованном поисковом документе. Хитрость заключается в том, чтобы также зашифровать места в документе (или базе данных), где присутствуют эти ключевые слова.


1

Программно эффективное решение заключается в

  1. получить ВСЕ записи для ТОЛЬКО поля, которое вы ищете с идентификатором записи
  2. расшифровать их во временную таблицу
  3. выполнить поиск по этой таблице
  4. использовать идентификаторы для получения полных записей (все поля), которые соответствуют критериям поиска
  5. расшифровать их и вернуть пользователю

Дело в том, что 1 и 4 представляют собой значительно меньшие наборы данных, чем извлечение и дешифрование всех полей всех записей в начале.

Надеюсь, это поможет.


Временные таблицы в незашифрованном виде относительно (то есть очень) легко захватить и прочитать, нарушить работу сервера в нужный момент или просто просто скопировать temp/папку и грохнуть, значения открытого текста для всего столбца есть, это не безопасный способ работы
Мартин

1

Это возможно при полной функциональности поиска с использованием внутренних функций шифрования MYSQL.

Вот пример:

!!! Я ИСПОЛЬЗУЮ MYSQL ENCODE () ЗДЕСЬ ДЛЯ ПРОСТОТЫ, MYSQL_ENCODE СЕЙЧАС РАССМОТРЕН НЕОБХОДИМЫМ, ИСПОЛЬЗУЙТЕ ОДНУ ВНУТРЕННУЮ ВНУТРЕННУЮ ФУНКЦИЮ MYSQL !!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

Как следует из приведенного выше комментария, НЕ используйте ENCODE (), используйте одну из других функций шифрования, в этом примере я использую только ENCODE из-за его простоты.

Если вы делаете это в приложении, таком как php, вы можете сделать это в своем шлюзе db или в классах репозитория, сохранив список / массив зашифрованных столбцов каждой таблицы в соответствующем классе шлюза.

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

Конечно, это очень грубый и небезопасный код, который нельзя использовать в производстве без значительных улучшений. Но это должно служить своей цели в предоставлении общей идеи.


-1

Предполагая, что вы выполняете поиск в SQL по полному значению, а не по частичному (например, LIKE 'value%') ... при захвате данных поиска, зашифруйте эти данные с помощью того же алгоритма, который использовался, когда данные были зашифрованы, и выполните поиск.

Например:

Что бы было:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

Может выглядеть вместо этого:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

1
Нет. Достойное шифрование будет работать со значением соли, поэтому, если, например, у вас есть уникальная соль для каждой строки, тогда соль каждой строки нужно будет использовать в строке поиска, это будет сложно и дорого, довольно быстро
Мартин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.