Шифрование в PL/SQL: уроки программирования

Возможности шифрования языка программирования PL/SQLВ простейшем определении шифрование представляет собой «маскировку» данных, или их преобразование, при котором данные не могут использоваться посторонними. Рассмотрим очень простой пример: я ежедневно снимаю деньги со своего счета при помощи кредитной карты. Каждый раз я должен ввести в банкомате свой PIN-код. К сожалению, я от природы весьма забывчив, поэтому я решаю записать PIN-код на предмете, который всегда под рукой при использовании карты, — то есть на самой карте. При этом я отлично понимаю, что PIN-код, написанный на карте, существенно ослабляет защиту; если карту украдут, то похититель сразу увидит написанный на ней код. Прощайте, сбережения! Что делать, чтобы вор не смог узнать PIN-код, но при этом не забыть его самому?



Через пару минут меня озаряет гениальная идея: цифры надо изменить заранее определенным образом. Я прибавляю к PIN-коду число из одной цифры и записываю результат на карте. Допустим, к PIN-коду 6523 прибавляется число 6; в сумме получается 6529, и я записываю это число на карте. Если карту украдут, то вор увидит код 6529, который будет совершенно бесполезен, потому что для восстановления PIN-кода нужно знать способ изменения исходного числа. Даже если он будет знать, что результат был получен сложением, ему нужно будет угадать число (6 в нашем случае). Иначе говоря, я зашифровал PIN-код и затруднил определение фактического значения.

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

  •  Метод изменения исходных данных (в данном случае прибавление числа к исходному значению).
  •  Конкретное прибавленное число (6).

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

 

Основная схема шифрования

Рис. 1. Основная схема шифрования

 

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

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

 

Длина ключа

У приведенного выше примера с шифрованием PIN-кода имеется серьезный недостаток. Вор может догадаться, что я просто прибавил число к PIN-коду, чтобы зашифровать его. Конечно, он не знает, что это за число, но он может перебирать возможные значения. Если я использую число из одной цифры, ему понадобится не более 10 попыток. Но предположим, я использую число из двух цифр — теперь придется угадывать число от 0 до 99, а число попыток увеличивается до 100. Увеличение количества цифр в ключе усложняет «взлом» шифра. Таким образом, длина ключа играет исключительно важную роль в повышении безопасности любой системы шифрования.

Конечно, в реальных схемах шифрования длина ключа не ограничивается одной-двумя цифрами. Более того, ключи вообще не состоят из одних цифр. Их длина обычно составляет не менее 56 бит, но может доходить и до 256 бит. Длина ключа зависит от выбора алгоритма (см. следующий раздел).

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

 

Алгоритмы

Существует немало распространенных, пользующихся коммерческой поддержкой алгоритмов шифрования. Впрочем, нас интересуют алгоритмы, поддерживаемые Oracle для приложений PL/SQL. Все эти алгоритмы относятся к категории алгоритмов с закрытым ключом (иногда называемых симметричными алгоритмами); основные их отличия от алгоритмов с открытым ключом (иногда называемых асимметричными) описаны во врезке.

В Oracle чаще всего используются следующие алгоритмы:

  •  DES (Data Encryption Standard). Традиционно алгоритм DES занимал ведущие позиции в области шифрования. Он был разработан более 20 лет назад для Национального бюро стандартов (позднее переименованного в Национальный институт стандартов и технологий), и с тех пор был принят в качестве стандарта ISO. Об алгоритме DES и его истории можно рассказать очень много, но моей задачей является не описание алгоритма, а краткое описание его применения. Алгоритму DES необходим 64-разрядный ключ, но 8 бит ключа не используются. Чтобы подобрать ключ, злоумышленнику придется перебрать до 72 057 594 037 927 936 комбинаций. Возможностей DES было достаточно в течение нескольких десятилетий, но сейчас он постепенно уходит в прошлое. Современные мощные компьютеры способны перебрать даже огромное число комбинаций, необходимое для взлома ключа DES.
  • DES3. В этой схеме, базирующейся на исходном алгоритме DES, данные шифруются дважды или трижды (в зависимости от режима вызова). DES3 использует 128- или 192-разрядный ключ; его длина определяется количеством проходов. Надежность алгоритма DES3 тоже была приемлемой в течение некоторого времени, но сейчас и этот алгоритм постепенно устаревает и не обеспечивает защиты от целенаправленных атак.
  •  AES. В ноябре 2001 года был одобрен новый стандарт AES (Advanced Encryption Standard), вступивший в силу в мае 2002 года. Полный текст стандарта можно найти по этому адресу.

 

открытый или ЗАКРЫТЫЙ ключ?

 

 

Заполнение и сцепление

Блок данных обычно не шифруется как единое целое. Чаще всего он разбивается на фрагменты по 8 байт, после чего каждый фрагмент шифруется независимо от других. Конечно, длина данных может быть не кратной 8 — в этом случае алгоритм добавляет символы в последний фрагмент до 8 байт. Этот процесс называется заполнением (padding). Если злоумышленник угадает, какие данные использовались для заполнения, это может упростить подбор ключа. Для безопасного заполнения следует использовать метод, реализованный в Oracle, называемый PKCS#5 (Public Key Cryptography System #5). Другие режимы (с заполнением нулями и вообще без заполнения) также будут представлены ниже.

Если данные делятся на фрагменты, также должен существовать способ объединения смежных фрагментов; этот процесс называется сцеплением (chaining). Безопасность системы шифрования также зависит от того, как происходит соединение и шифрование фрагментов (независимо или в сочетании со смежными фрагментами). Самым распространенным форматом сцепления является формат CBC (Cipher Block Chaining);

в Oracle он выбирается при помощи константы, определенной во встроенном пакете CHAIN_CBC. Также используются режимы сцепления Electronic Code Book (CHAIN_ ECB), Cipher Feedback (CHAIN_CFB) и Output Feedback (CHAIN_OFB). Они тоже будут представлены позднее в моем блоге.

 

Пакет DBMS_CRYPTO

Итак, мы познакомились с основными структурными элементами схем шифрования. Давайте посмотрим, как создать инфраструктуру шифрования в PL/SQL с использованием встроенного пакета Oracle DBMS_CRYPTO.

Пакет DBMS_CRYPTO появился в Oracle10g. В более ранних версиях пакет DBMS_OBFUSCATION_TOOLKIT предоставлял похожую (но не идентичную) функциональность. Старый пакет все еще остается доступным, но сейчас он считается устаревшим, и вместо него рекомендуется использовать новый пакет.

Вспомните, что для выполнения шифрования кроме входных данных необходимы еще четыре компонента:

  •  ключ шифрования;
  •  алгоритм шифрования;
  •  метод заполнения;
  •  метод сцепления.

Ключ шифрования предоставляете вы, а остальные компоненты предоставляет Oracle. Выбор осуществляется при помощи соответствующих констант пакета DBMS_CRYPTO.

 

Алгоритмы

В табл. 1 перечислены константы DBMS_CRYPTO, позволяющие выбрать конкретный алгоритм и длину ключа. Ссылки на эти константы должны задаваться в формате имя_пакета .имя_константы — например, DBMS_CRYPTO.ENCRYPT_DES для выбора алгоритма DES.

 

Таблица 1. Константы алгоритмов пакета DBMS_CRYPTO

Константа Фактическая длина ключа Описание
ENCRYPT_DES 56 DES (по аналогии с DBMS_OBFUSCATION_TOOLKIT)
ENCRYPT_3DES_2KEY 112 Модифицированный DES3; блок шифруется в три прохода
с двумя ключами
ENCRYPT_3DES 156 DES3; блок шифруется в три прохода
ENCRYPT_AES128 128 AES
ENCRYPT_AES192 192 AES
ENCRYPT_AES256 256 AES
ENCRYPT_RC4 - Единственный потоковый шифр, поддерживаемый пакетом
(предназначен для шифрования потоковых, а не дискретных
данных)

 

 

Заполнение и сцепление

Режимы заполнения и сцепления задаются при помощи констант пакета DBMS_CRYPTO, перечисленных в табл. 2.

 

Таблица 2. Методы заполнения и сцепления пакета DBMS_CRYPTO

Константа Метод заполнения/сцепления
PAD_PCKS5 Заполнение PKCS#5
PAD_ZERO Заполнение нулями
PAD_NONE Заполнение не используется; метод выбирается для данных, длина которых кратна
8 байтам
CHAIN_CBC Cipher Block (самый распространенный метод)
CHAIN_CFB Cipher Feedback
CHAIN_ECB Electronic Code Book
CHAIN_OFB Output Feedback

 

 

Вам почти не придется беспокоиться о выборе конкретного метода заполнения или сцепления; как правило, разные методы предлагают специфические возможности, редко необходимые при разработке типичных систем.

Чаще всего на практике выбирается метод заполнения PKCS#5 с методом сцепления CBC. В моем блоге они будут использоваться во всех случаях, кроме тех, где обратное явно указано в тексте.

 

Шифрование данных

Начнем с очень простого примера шифрования строки «Confidential Data» функцией DBMS_CRYPTO.ENCRYPT. Функция получает четыре аргумента:

  •  src — исходные данные, подлежащие шифрованию (должны иметь тип данных RAW).
  •  key — ключ шифрования (также RAW). Длина ключа должна соответствовать выбранному алгоритму. Например, для алгоритма DES она должна быть не менее 64 бит.
  •  typ — определение трех компонентов (алгоритм, механизм заполнения и метод сцепления) в виде суммы соответствующих констант.
  •  iv — необязательный вектор инициализации (IV), еще один компонент схемы шифрования, затрудняющий анализ «закономерностей» в зашифрованном тексте (эта тема выходит за рамки настоящей статьи).

В следующих примерах будут использоваться:

  •  алгоритм — AES c 128-разрядным ключом;
  •  метод сцепления — CBC;
  •  механизм заполнения — PKCS#5.

Они задаются следующим значением параметра typ при вызове функции:

DBMS_CRYPTO.ENCRYPT_AES128
  + DBMS_CRYPTO.CHAIN_CBC
  + DBMS_CRYPTO.PAD_PKCS5;

Если бы вместо PKCS#5 был выбран режим без заполнения, значение выглядело бы так:

DBMS_CRYPTO.ENCRYPT_AES128
  + DBMS_CRYPTO.CHAIN_CBC
  + DBMS_CRYPTO.PAD_NONE;

Аналогичным образом задается любая другая комбинация алгоритма и метода сцепления.

Затем необходимо выбрать ключ. Предположим, в качестве ключа будет использоваться строка «1234567890123456». Это значение относится к типу данных VARCHAR2. Чтобы использовать его в функции ENCRYPT, необходимо сначала преобразовать его к типу RAW. Для этого мы воспользуемся функцией STRING_T0_RAW встроенного пакета UTL_I18N:

DECLARE
   l_raw    RAW (200);
   l_in_val VARCHAR2 (200) := 'Confidential Data';
BEGIN
   l_raw := utl_i18n.string_to_raw (l_in_val, 'AL32UTF8');
END;

Переменная l_in_val типа VARCHAR2 преобразована к типу RAW. Теперь можно переходить непосредственно к шифрованию входных данных:

/* File on web: enc.sql */
 1   DECLARE
 2       l_key      VARCHAR2 (2000) := '1234567890123456';
 3       l_in_val   VARCHAR2 (2000) := 'Confidential Data';
 4       l_mod      NUMBER
 5          :=   DBMS_CRYPTO.encrypt_aes128
 6             + DBMS_CRYPTO.chain_cbc
 7             + DBMS_CRYPTO.pad_pkcs5;
 8       l_enc      RAW (2000);
 9   BEGIN
10       l_enc :=
11          DBMS_CRYPTO.encrypt (utl_i18n.string_to_raw (l_in_val, 'AL32UTF8'),
12                               l_mod,
13                               utl_i18n.string_to_raw (l_key, 'AL32UTF8')
14                              );
15       DBMS_OUTPUT.put_line ('Encrypted=' || l_enc);
16   END;

Результат:

Encrypted=C0777257DFBF8BA9A4C1F724F921C43C70D0C0A94E2950BBB6BA2FE78695A6FC

Давайте проанализируем этот код, строку за строкой.

 

Строки Описание
2 Определение ключа. Длина ключа составляет ровно 16 символов (128 бит), в соответствии с требованиями AES. Если бы был выбран алгоритм AES192, я задал бы длину ключа равной 192/8=24. При неверной длине ключа выдается исключение
3 Входные данные для шифрования. Длина данных не ограничивается; допускается использование значения произвольной длины. Если длина не кратна 8 байтам, входные данные автоматически дополняются до нужной длины в соответствии с выбранным алгоритмом
4-7 Определение алгоритма, метода заполнения и метода сцепления
8 Определение переменной для хранения зашифрованного значения. Обратите внимание: выходные данные имеют тип RAW
11 Входные данные преобразуются из типа VARCHAR2 в тип RAW
13 Ключ тоже должен передаваться функции в формате RAW
15 Вывод зашифрованного значения (тоже в формате RAW) в виде шестнадцатеричной строки. В реальной системе выводить значение бессмысленно; вероятно, с ним будет выполнена другая операция: сохранение в таблице, передача вызывающей процедуре для использования в другом месте и т. д.

 

На базе ENCRYPT можно построить обобщенную функцию шифрования данных. В этой функции будет использоваться алгоритм AES с 128-разрядным ключом, метод заполнения PCKS#5 и метод сцепления CBC. Таким образом, при вызове функции пользователь должен предоставить только шифруемые данные и ключ.

/* File on web: get_enc_eval.sql */
FUNCTION get_enc_val (p_in_val IN VARCHAR2, p_key IN VARCHAR2)
   RETURN VARCHAR2
IS
   l_enc_val   RAW (4000);
BEGIN
   l_enc_val :=
      DBMS_CRYPTO.encrypt (src      => utl_i18n.string_to_raw (p_in_val,
                                                               'AL32UTF8'
                                                              ),
                           key      => utl_i18n.string_to_raw (p_key,
                                                               'AL32UTF8'
                                                              ),
                           typ      =>   DBMS_CRYPTO.encrypt_aes128
                                       + DBMS_CRYPTO.chain_cbc
                                       + DBMS_CRYPTO.pad_pkcs5
                          );
   RETURN l_enc_val;
END;

 

Напоследок осталось упомянуть еще об одном обстоятельстве. Для преобразования данных VARCHAR2 в RAW используется функция UTL_I18N.STRING_TO_RAW вместо UTL_RAW. CAST_TO_RAW. Почему?

Входные данные функции ENCRYPT должны иметь тип RAW и при этом использовать конкретный набор символов AL32UTF8, который может и не совпадать с набором символов базы данных. Следовательно, при проектировании строки VARCHAR2 в RAW для шифрования необходимо выполнить два преобразования:

  •  Из текущего набора символов базы данных в набор AL32UTF8.
  •  Из VARCHAR2 в RAW.

Оба преобразования выполняются функцией STRING_T0_RAW встроенного пакета UTL_IL8N; функция CAST_T0_RAW не изменяет набор символов.

Пакет UTL_IL8N является частью архитектуры Oracle Globalization Support и предназначен для глобализации (или интернализации) приложений.

 

Шифрование LOB

Большие объектные типы данных — такие, как CL0B и BLOB, — тоже могут шифроваться. Например, в данных BLOB могут храниться файлы сигнатур и копии юридических документов. Содержимое таких файлов конфиденциально, поэтому при хранении в базе данных их желательно зашифровать. Вместо того чтобы вызывать функцию ENCRYPT, как это делалось в предыдущих примерах, я воспользуюсь перегруженной процедурной версией ENCRYPT:

/* File on web: enc_lob.sql */
DECLARE
   l_enc_val   BLOB;
   l_in_val    CLOB;
   l_key       VARCHAR2 (16) := '1234567890123456';
BEGIN
   DBMS_CRYPTO.encrypt (dst      => l_enc_val,
                        src      => l_in_val,
                        key      => utl_i18n.string_to_raw (l_key, 'AL32UTF8'),
                        typ      =>   DBMS_CRYPTO.encrypt_aes128
                                    + DBMS_CRYPTO.chain_cbc
                                    + DBMS_CRYPTO.pad_pkcs5
                       );
END;

Результат сохраняется в переменной l_enc_val, которая затем может передаваться другим программам или сохраняться в таблице.

Для данных LOB используйте процедурную версию ENCRYPT; для всех остальных типов данных используйте функцию. Не забудьте преобразовать значения в формат RAWCLOB — в BLOB), прежде чем передавать их функции ENCRYPT.

 

SecureFiles

Большие объекты (LOB) были значительно переработаны в Oracle Database 11g; теперь для их обозначения используется термин SecureFiles. Традиционные объекты LOB (теперь называемые BasicFiles), такие как CLOB и BLOB, по-прежнему доступны, но я не рекомендую их использовать. В любых ситуациях, в которых в прошлом использовались LOB, теперь следует использовать SecureFiles. Технология SecureFiles предоставляет ту же функциональность, что и LOB, а также ряд дополнительных возможностей — таких, как сжатие, устранение дубликатов, кэширование, возможность прекращения ведения журнала и т. д. За дополнительной информацией об использовании SecureFiles обращайтесь к этой статье.

 

Дешифрование данных

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

  •  src — зашифрованные данные.
  •  key — ключ, использованный для шифрования.
  •  typ — три компонента (алгоритм, механизм заполнения и метод сцепления), использованные при вызове ENCRYPT.
  •  iv — вектор инициализации, использованный при вызове ENCRYPT.

Функция DECRYPT тоже возвращает дешифрованные данные в формате RAW; для нормального просмотра их необходимо преобразовать в другой формат.

Давайте посмотрим, как работает дешифрование. В следующем примере зашифрованное значение сохраняется в переменной SQL*Plus, а затем используется в качестве исходных данных для функции DECRYPT.

/* File on the web decval.sql */
 1    REM Define a variable to hold the encrypted value
 2    VARIABLE enc_val varchar2(2000);
 3    DECLARE
 4       l_key      VARCHAR2 (2000) := '1234567890123456';
 5       l_in_val   VARCHAR2 (2000) := 'Confidential Data';
 6       l_mod      NUMBER
 7          :=   DBMS_CRYPTO.encrypt_aes128
 8             + DBMS_CRYPTO.chain_cbc
 9             + DBMS_CRYPTO.pad_pkcs5;
10       l_enc      RAW (2000);
11    BEGIN
12       l_enc :=
13          DBMS_CRYPTO.encrypt (utl_i18n.string_to_raw (l_in_val, 'AL32UTF8'),
14                               l_mod,
15                               utl_i18n.string_to_raw (l_key, 'AL32UTF8')
16                              );
17       DBMS_OUTPUT.put_line ('Encrypted=' || l_enc);
18       :enc_val := RAWTOHEX (l_enc);
19    END;
20    /
21    DECLARE
22       l_key      VARCHAR2 (2000) := '1234567890123456';
23       l_in_val   RAW (2000)      := HEXTORAW (:enc_val);
24       l_mod      NUMBER
25          :=   DBMS_CRYPTO.encrypt_aes128
26             + DBMS_CRYPTO.chain_cbc
27             + DBMS_CRYPTO.pad_pkcs5;
28       l_dec      RAW (2000);
29    BEGIN
30       l_dec :=
31          DBMS_CRYPTO.decrypt (l_in_val,
32                               l_mod,
33                               utl_i18n.string_to_raw (l_key, 'AL32UTF8')
34                              );
35       DBMS_OUTPUT.put_line ('Decrypted=' || utl_i18n.raw_to_char (l_dec));
36    END;

Основные моменты этого кода разъясняются в следующей таблице.

  

Строки Описание
22 Объявление ключа для дешифрования. Обратите внимание: он должен совпадать с ключом, использованным при шифровании
23 Так как переменная enc_val содержит шестнадцатеричное значение, мы преобразуем ее к типу RAW
25-27 Как и при шифровании, необходимо задать алгоритм, методы заполнения и сцепления в одном параметре. Это значение должно совпадать с тем, которое использовалось при шифровании
33 Как и при шифровании, ключ должен храниться в переменной типа RAW, поэтому он преобразуется из VARCHAR2 в RAW

 

Код выводит строку «Confidential Data» — ту, которая была изначально зашифрована.

Для расшифровки зашифрованного объекта LOB необходимо использовать перегруженную процедурную версию DECRYPT, потому что для шифрования использовалась процедурная версия ENCRYPT.

 

Генерирование ключей

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

В стандарте ANSI X9.31: Pseudo-Random Number Generator (PRNG) определяется стандартный алгоритм создания случайных чисел. Oracle реализует этот алгоритм в функции RANDOMBYTES пакета DBMS_CRYPTO. Функция получает один аргумент с длиной генерируемой случайной строки и возвращает значение заданной длины в формате RAW. Пример ее использования для создания 16-байтового значения:

DECLARE
   l_key   RAW (16);
BEGIN
   l_key := DBMS_CRYPTO.randombytes (16);
END;

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

 

Управление ключами

Мы рассмотрели азы шифрования/дешфирования, научились генерировать ключи. Но это была самая простая часть; в основном я просто показывал, как пользоваться готовыми средствами Oracle для достижения желаемой цели. Пора переходить к самой сложной части инфраструктуры шифрования — управлению ключами. Ключ должен быть доступен для наших приложений, чтобы они могли дешифровать зашифрованные значения, и механизм обращения к ключу должен быть по возможности простым. С другой стороны, поскольку ключ буквально является «ключом», защищающим зашифрованные данные, он не должен быть слишком доступным. Качественная схема управления ключами совмещает доступность ключей с предотвращением несанкционированного доступа к ним. Известны три основных схемы управления ключами:

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

Ниже приводятся краткие описания этих разных подходов к управлению ключами.

 

Один ключ для всей базы данных


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

 

Схема с одним ключом

рис. 2. Схема с одним ключом

 

Ключ может храниться в разных местах:

  •  В базе данных. Самая простая стратегия из всех. Ключ хранится в реляционной таблице, возможно, в схеме, предназначенной специально для этой цели. Поскольку ключ хранится в базе данных, он автоматически сохраняется при создании резервной копии базы данных; старые значения ключа могут быть получены при помощи ретроспективных запросов, а сам ключ защищен от похищения на уровне операционной системы. Простота имеет и обратные стороны; так как ключ представляет собой обычные данные в таблице, любой пользователь с полномочиями модификации таблицы (например, администратор базы данных) может изменить ключ и разрушить всю инфраструктуру шифрования.
  •  В файловой системе. Ключ хранится в файле и читается процедурой шифрования с использованием встроенного пакета UTL_FILE. Задавая соответствующие привилегии доступа к файлу, можно защитить ключ от изменения из базы данных.
  •  На съемном носителе под контролем пользователя. Это самый безопасный способ — никто, кроме пользователя, не сможет расшифровать данные или изменить ключ, даже администратор базы данных или системы. В качестве съемного носителя может использоваться USB-диск, DVD или даже съемный жесткий диск. Главным недостатком съемного носителя является возможность потери ключа. Ответственность за безопасность ключа возлагается на пользователя. Если ключ будет потерян, то все зашифрованные данные пропадут — безвозвратно.

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

 

Один ключ для каждой строки

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

Главное преимущество этого подхода заключается в том, что каждая запись защищается собственным ключом. Если один ключ будет подобран, то под контролем злоумышленника окажется только одна строка, а не вся база данных. Изменение ключа распространяется не на всю базу данных, а только на одну строку, которая достаточно легко изменяется. С другой стороны, при таком подходе ключ всегда должен храниться в базе данных. Хранение ключей в файловой системе так, чтобы они были доступны для базы данных, может оказаться неприемлемым. Кроме того, усложняется защита файла базы данных в случае похищения как ключей, так и зашифрованных данных.

 

Комбинированная схема

Комбинированная схема стремится объединить высокую степень безопасности с максимальной гибкостью. Для каждой строки создается свой ключ, но в базе данных также имеется главный ключ (рис. 4). Процесс шифрования не сводится к простому использованию ключа, хранимого для каждой записи. Вместо этого ключ строки объединяется с главным ключом поразрядной операцией XOR, а полученное значение используется в качестве ключа строки. Чтобы расшифровать значение, необходимо знать как ключ строки (хранящийся в базе данных), так и главный ключ (хранящийся в другом месте). Раздельное хранение этих ключей повышает уровень безопасности схемы шифрования.

Схема с одним ключом для каждой строки

Рис. 3. Схема с одним ключом для каждой строки

 

 

Комбинированная схема

Рис. 4. Комбинированная схема

 

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

Эта схема не эквивалентна повторному шифрованию зашифрованного значения с другим ключом. Пакет DBMS_CRYPTO не позволяет повторно шифровать зашифрованные данные, если вы попытаетесь это сделать, Oracle выдаст ошибку ORA-28233.

Рассмотрим пример использования этой схемы в реальном приложении. В код, уже приводившийся ранее при описании дешифрования, добавляется новая переменная l_master_key (строка 6), которая получает значение от пользователя (подстановочная переменная &master_key). В строках 14-18 ключ объединяется операцией XOR с главным ключом, который использовался при шифровании в строке 22, вместо переменной l_key.

/* File on web: combined_master_key.sql */
1    REM Define a variable to hold the encrypted value
2    VARIABLE enc_val varchar2(2000);
3    DECLARE
4       l_key          VARCHAR2 (2000) := '1234567890123456';
5       l_master_key   VARCHAR2 (2000) := '&master_key';
6       l_in_val       VARCHAR2 (2000) := 'Confidential Data';
7       l_mod          NUMBER
8          :=   DBMS_CRYPTO.encrypt_aes128
9             + DBMS_CRYPTO.chain_cbc
10             + DBMS_CRYPTO.pad_pkcs5;
11       l_enc          RAW (2000);
12       l_enc_key      RAW (2000);
13    BEGIN
14       l_enc_key :=
15          UTL_RAW.bit_xor (utl_i18n.string_to_raw (l_key, 'AL32UTF8'),
16                           utl_i18n.string_to_raw (l_master_key, 'AL32UTF8')
17                          );
18       l_enc :=
19          DBMS_CRYPTO.encrypt (utl_i18n.string_to_raw (l_in_val, 'AL32UTF8'),
20                               l_mod,
21                               l_enc_key
22                              );
23       DBMS_OUTPUT.put_line ('Encrypted=' || l_enc);
24       :enc_val := RAWTOHEX (l_enc);
25    END;
26    /
27    DECLARE
28       l_key          VARCHAR2 (2000) := '1234567890123456';
29       l_master_key   VARCHAR2 (2000) := '&master_key';
30       l_in_val       RAW (2000)      := HEXTORAW (:enc_val);
31       l_mod          NUMBER
32          :=   DBMS_CRYPTO.encrypt_aes128
33             + DBMS_CRYPTO.chain_cbc
34             + DBMS_CRYPTO.pad_pkcs5;
35       l_dec          RAW (2000);
36       l_enc_key      RAW (2000);
37    BEGIN
38       l_enc_key :=
39          UTL_RAW.bit_xor (utl_i18n.string_to_raw (l_key, 'AL32UTF8'),
40                           utl_i18n.string_to_raw (l_master_key, 'AL32UTF8')
41                          );
42       l_dec := DBMS_CRYPTO.decrypt (l_in_val, l_mod, l_enc_key);
43       DBMS_OUTPUT.put_line ('Decrypted=' || utl_i18n.raw_to_char (l_dec));
44    END;

 

При выполнении этого блока в SQI*Plus будет получен следующий результат (обратите внимание: сначала главный ключ вводится для шифрования данных, а затем тот же главный ключ вводится при дешифровании):

Enter value for master_key: MasterKey0123456
old   3:     l_master_key varchar2(2000) := '&master_key';
new   3:     l_master_key varchar2(2000) := 'MasterKey0123456';
Encrypted=C2CABD4FD4952BC3ABB23BD50849D0C937D3EE6659D58A32AC69EFFD4E83F79D

PL/SQL procedure successfully completed.

Enter value for master_key: MasterKey0123456
old   3:     l_master_key varchar2(2000) := '&master_key';
new   3:     l_master_key varchar2(2000) := 'MasterKey0123456';
Decrypted=ConfidentialData

PL/SQL procedure successfully completed.

Программа запросила главный ключ, который был введен правильно, и программа выдала правильное значение. А что произойдет, если главный ключ задан неверно?

Enter value for master_key: MasterKey0123456
old   3:     l_master_key varchar2(2000) := '&master_key';
new   3:     l_master_key varchar2(2000) := 'MasterKey0123456';
Encrypted=C2CABD4FD4952BC3ABB23BD50849D0C937D3EE6659D58A32AC69EFFD4E83F79D

PL/SQL procedure successfully completed.

Enter value for master_key: MasterKey0123455
old   3:     l_master_key varchar2(2000) := '&master_key';
new   3:     l_master_key varchar2(2000) := 'MasterKey0123455';
declare
*
ERROR at line 1:
ORA-28817: PL/SQL function returned an error.
ORA-06512: at "SYS.DBMS_CRYPTO_FFI", line 67
ORA-06512: at "SYS.DBMS_CRYPTO", line 41
ORA-06512: at line 15

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

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

  •  Создайте между сервером приложения и сервером базы данных виртуальную локальную сеть (VLAN), которая в значительной степени защищает передаваемый сетевой трафик.
  •  Главный ключ можно изменить некоторым заранее определенным способом — скажем, инвертировать все символы. В этом случае злоумышленник получит не главный ключ, а его модификацию, передаваемую по сети.
  •  Наконец, если вам необходимо действительно безопасное решение, защитите трафик между клиентом и сервером при помощи Oracle Advanced Security Option (поставляется за отдельную плату).

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

 

Криптографическое хеширование

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

Задача решается при помощи процесса, называемого криптографическим хешированием. В результате применения функции криптографического хеширования к некоторым данным генерируется новое значение, по которому невозможно «восстановить» исходные данные и которое с большой вероятностью является уникальным. Хеш-функции также обладают свойством детерминированности, то есть для одних исходных данных хеш-функция всегда возвращает один и то же хеш-код.

Хеширование не является разновидностью шифрования, потому что по хеш-коду невозможно получить исходные данные. Хеширование дает непрозрачный «след» исходных данных, хранимый отдельно от них. Когда возникает необходимость в проверке подлинности данных, вы снова генерируете хеш-код и сравниваете его с хранимым хеш- кодом. Если исходные данные изменились, то и хеш-код тоже изменится, и вы сможете выполнить соответствующие действия.

Теоретически для двух разных исходных значений могут быть сгенерированы одинаковые хеш-коды. Однако широко распространенные алгоритмы (такие, как MD5 и SHA-1) гарантируют, что вероятность конфликтов составляет статистически ничтожную величину 1/1038. Если вас не устраивает даже такая вероятность, вам придется реализовать собственную логику разрешения конфликтов.

В Oracle поддерживаются два вида хеширования: MD5 (Message Digest) и SHA-1 (Secure Hash Algorithm). Оба реализованы в функции HASH пакета DBMS_CRYPTO. Функция HASH получает два аргумента:

  •  src — исходные данные, для которых генерируется хеш-код. Значение должно иметь тип RAW, как и в случае с функцией ENCRYPT. Если хешируемые данные хранятся в формате VARCHAR2 или NUMBER, их необходимо преобразовать к типу RAW.
  •  typ — алгоритм хеширования: MD4, MD5, SHA-1 или разновидности SHA-2. Параметр передается в виде одной из констант пакета DBMS_CRYPTO:
DBMS_CRYPTO.HASH_SH1
DBMS_CRYPTO.HASH_SH256
DBMS_CRYPTO.HASH_SH384
DBMS_CRYPTO.HASH_SH512
DBMS_CRYPTO.HASH_MD5
DBMS_CRYPTO.HASH_MD4

Разумеется, префикс SHA в именах констант относится к алгоритму хеширования SHA: SH1 — для метода SHA-1. SHA-2 — более новый и криптографически более защищенный метод хеширования, поддерживаемый в PL/SQL начиная с Oracle Database 12c. Доступны три разновидности хеширования SHA-2SHA256, SHA384 и SHA512, в зависимости от используемой длины ключа. В следующем примере объявляются две локальные переменные: для исходных данных и генерируемого хеш-кода. Затем вызывается функция HASH с выбором алгоритма хеширования SHA-1:

/* File on web: hash.sql */
 1    DECLARE
 2       l_in_val   VARCHAR2 (2000) := 'CriticalData';
 3       l_hash     RAW (2000);
 4    BEGIN
 5       l_hash :=
 6          DBMS_CRYPTO.HASH (src      => utl_i18n.string_to_raw (
 7                                           l_in_val, 'AL32UTF8'
 8                                                               ),
 9                            typ      => DBMS_CRYPTO.hash_sh1
10                           );
11       DBMS_OUTPUT.put_line ('Hash=' || l_hash);
12    * END;

Программа выводит сгенерированный хеш-код: Hash=9222DE984C1A7DD792F680FDFD3EA05CB6CA59A9

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

Хеширование применяется во многих областях, не связанных с криптографией. Например, веб-приложения по своей природе не имеют состояния; сеанс приложения не обязательно соответствует «сеансу» экземпляра Oracle. Соответственно, блокировки уровня строк не гарантируют защиты от потерянных обновлений; после того как вебстраница загрузит строку, другое приложение может изменить данные. Как сеанс вебприложения узнает об изменении загруженной ранее страницы? Одно из возможных решений заключается в генерировании и сохранении хеш-кодов данных строк. Когда в будущем приложению понадобится работать со строкой, оно выполняет повторное хеширование, сравнивает значения и быстро определяет актуальность данных.

 

Коды MAC

Хеширование предназначено для проверки подлинности данных, а не для их защиты от посторонних. Идея заключается в том, что вы генерируете хеш-код и сохраняете его в другом месте, отличном от места хранения самих данных. Позднее хеширование производится заново, а результат сравнивается с сохраненным значением. Однако при этом возникает небольшая проблема: что делать, если злоумышленник обновит исходные данные, выполнит хеширование и обновит сохраненный хеш-код?

Для предотвращения подобных неприятностей создается своего рода хеш-код, защищенный паролем, — он называется кодом MAC (Message Authentication Code). Код MAC представляет собой хеш-код, объединенный с ключом. При использовании другого ключа на основании тех же исходных данных будет сгенерирован другой код MAC. Использование ключа не позволяет злоумышленнику сгенерировать тот же код MAC, если только он не угадает ключ (поэтому не используйте очевидные значения!). Алгоритм MAC реализуется функцией MAC пакета DBMS_CRYPTO. Функция получает три параметра:

  •  src — исходные данные (raw).
  •  key — ключ, используемый для вычисления кода MAC.
  •  typ — используемый алгоритм. Как и при хешировании, доступны три варианта: MD4, MD5 и SHA-1. Параметр передается в виде константы пакета DBMS_CRYPTO (см. список в предыдущем разделе). Единственное отличие — замена префикса «HASH» в именах на «HMAC»; например, константа MAC для алгоритма SHA-1 называется HMAC_SH1 вместо HASH_SH1.

Следующий пример практически идентичен тому, который использовался для демонстрации хеширования, кроме добавления ключа «1234567890123456». И ключ, и исходные данные должны относиться к типу RAW; если они хранятся в переменной другого типа, их необходимо преобразовать.

 

DECLARE
   l_in_val   VARCHAR2 (2000) := 'Critical Data';
   l_key      VARCHAR2 (2000) := 'SecretKey';
   l_mac      RAW (2000);
BEGIN
   l_mac :=
      DBMS_CRYPTO.mac (src      => utl_i18n.string_to_raw (l_in_val,'AL32UTF8'),
                       typ      => DBMS_CRYPTO.hmac_sh1,
                       KEY      => utl_i18n.string_to_raw (l_key, 'AL32UTF8')
                      );
   DBMS_OUTPUT.put_line ('MAC=' || l_mac);
   -- let's use a different key
   l_key := 'Another Key';
   l_mac :=
      DBMS_CRYPTO.mac (src      => utl_i18n.string_to_raw (l_in_val,'AL32UTF8'),
                       typ      => DBMS_CRYPTO.hmac_sh1,
                       KEY      => utl_i18n.string_to_raw (l_key, 'AL32UTF8')
                      );
   DBMS_OUTPUT.put_line ('MAC=' || l_mac);
END;

Результат:

MAC=7A23524E8B665A57FE478FBE1D5BFE2406906B2E
MAC=0C0E467B588D2AD1DADE7393753E3D67FCCE800C

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

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

 

Прозрачное шифрование данных

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

Начиная с Oracle Database 10g Release 2 механизм прозрачного шифрования данных (TDE, Transparent Data Encryption) сильно упрощает шифрование. Все, что для этого нужно, — пометить столбец как зашифрованный; Oracle сделает все остальное. Значение столбца обрабатывается при вводе пользователем, шифруется и сохраняется в зашифрованном формате. В будущем при запросе данных значение автоматически дешифруется, и результат возвращается пользователю, которому даже не нужно знать о выполняемом шифровании и дешифровании, — отсюда и термин «прозрачный». Все происходит в коде Oracle без необходимости применения триггеров или сложной процедурной логики. Рассмотрим пример использования TDE: чтобы объявить столбец SSN таблицы ACCOUNTS как зашифрованный, достаточно включить в команду следующее условие:

ALTER TABLE accounts MODIFY (ssn ENCRYPT USING 'AES256')

База данных Oracle шифрует столбец SSN с применением алгоритма AES и 256-разрядного ключа. Ключ хранится в таблице словаря данных, но для его защиты от похищения он также шифруется с главным ключом, хранящимся в отдельном месте — электронном бумажнике. Бумажник по умолчанию хранится в каталоге $ORACLE_BASE/admin/$ORACLE_SID/wallet; впрочем, в файле SQLNET.ORA можно выбрать другое местонахождение. Допустим, пользователь вводит данные:

INSERT INTO accounts (ssn) VALUES ('123456789')

Фактическое значение сохраняется в зашифрованном виде в файлах данных, журналах операций и их архивах, а значит, и в резервных копиях. При следующих обращениях пользователя к данным зашифрованное значение автоматически дешифруется, и пользователь получает исходное значение. Перед выполнением приведенных команд бумажник должен быть открыт администратором базы данных или администратором по безопасности. Начиная с Oracle Database 12c в секции шифрования появился еще один параметр, обеспечивающий дополнительную защиту шифруемых данных: к каждому зашифрованному значению добавляется 20-байтовый код MAC. Если кто-то изменит зашифрованное значение, код MAC измененных данных будет отличаться от исходного, и модификация данных будет обнаружена. Однако добавление кода MAC увеличивает затраты памяти на хранение данных, что может создать проблемы в базах данных, ограниченных по занимаемому пространству. Эту функцию можно отключить:

ALTER TABLE accounts MODIFY (ssn ENCRYPT USING 'AES256' NOMAC)

Как видите, использовать TDE очень просто, поэтому возникает закономерный вопрос: насколько актуально все, что говорилось ранее о шифровании в этойстатье?

 

Кратко о шифровании

 


Вовсе нет! Область применения TDE ограничена защитой файлов базы данных от возможного похищения посредством шифрования конфиденциальной информации с минимальными усилиями. Однако следует обратить особое внимание на слово «прозрачный» в названии технологии — то есть автоматически выполняется как шифрование, так и дешифрование данных. Oracle не различает пользователей в контексте базы данных. Когда пользователь обращается с запросом к данным, Oracle предоставляет текстовое значение независимо от того, кто выдал запрос.

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

У TDE имеются свои ограничения. Во-первых, технология TDE не может использоваться для шифрования столбца внешнего ключа; во многих бизнес-приложениях это может стать серьезным препятствием. Кроме того, для столбцов, защищенных TDE, могут создаваться только индексы B-деревьев. При самостоятельной реализации шифрования средствами PL/SQL такие ограничения отсутствуют.

Принимая решение о том, подойдет ли TDE для ваших целей, также необходимо принять во внимание другой аспект — автоматизацию. В TDE электронный бумажник (в котором хранится главный ключ) должен быть открыт администратором базы данных, для чего используется команда следующего вида:

ALTER SYSTEM SET ENCRYPTION WALLET OPEN AUTHENTICATED BY "pooh";

Здесь "pooh" — пароль к бумажнику. Если файлы базы данных (или журналы операций, или резервные копии этих файлов) будут похищены, то зашифрованные столбцы останутся недоступными — вор не знает пароль, который позволит ему открыть бумажник. После каждого запуска базы данных вставка или обращение к зашифрованным столбцам станут возможны лишь после того, как бумажник будет явно открыт администратором. Если бумажник закрыт, операции вставки и попытки обращения к этим столбцам завершатся неудачей. После открытия базы данных необходимо выполнить одно лишнее действие; кроме того, человек, открывающий базу данных, должен знать пароль к бумажнику. В принципе для упрощения и автоматизации процесса можно создать триггер запуска базы данных, который вызывает команду ALTER SYSTEM (см. выше). Но в этом случае вы лишаете единственной защиты свой бумажник — а следовательно, и зашифрованные столбцы. Итак, при использовании TDE такие триггеры создавать никогда не следует, а вы должны быть готовы к выполнению лишней операции при каждом запуске базы данных. Однако самостоятельно реализованная инфраструктура шифрования станет доступна одновременно с базой данных; никакие дополнительные действия не потребуются, а вам не придется запоминать и вводить пароли от бумажника.

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

 

Прозрачное шифрование табличного пространства

Итак, основные недостатки TDE (и в меньшей степени — пользовательских реализаций шифрования) в отношении производительности приложения:

  •  TDE не позволяет использовать индексы для диапазонных запросов, поскольку табличные данные не коррелируют со значениями индекса. Пользовательская реализация шифрования предоставляет ограниченные возможности для использования индексов.
  •  Запросы к шифрованным данным требуют дешифрования, что приводит к существенным дополнительным затратам вычислительных ресурсов.

По этим причинам при разработке реальных приложений технология TDE часто отвергается как неприемлемая, а обширные требования к пользовательским реализациям шифрования на базе DBMS_CRYPTO создают изрядные трудности во многих организациях. Для решения этих проблем в Oracle Database 11g появилась новая технология прозрачного шифрования табличного пространства (TTE, Transparent Tablespace Encryption). Она позволяет включить шифрование для всего табличного пространства, а не для отдельных таблиц. Пример создания шифрованного табличного пространства:

TABLESPACE securets1
   DATAFILE '+DG1/securets1_01.dbf'
   SIZE 10M
   ENCRYPTION USING 'AES128'
   DEFAULT STORAGE (ENCRYPT)

Все объекты, создаваемые в этом табличном пространстве, должны преобразовываться в зашифрованный формат по алгоритму AES с использованием 128-разрядного ключа. Для этого необходимо заранее создать бумажник и открыть его так, как описано в предыдущем разделе. Ключ шифрования хранится в таблице ENC$ в зашифрованном виде, а ключ к этому шифрованию хранится в бумажнике (как и в случае TDE). Конечно, бумажник должен быть открыт до создания табличного пространства.

Как шифрование табличного пространства поможет решить проблемы шифрования уровня таблиц, спросите вы? Принципиальное отличие между двумя технологиями заключается в том, что данные в табличном пространстве шифруются только на диске; сразу же после чтения данные дешифруются и помещаются в буферный кэш SGA в виде простого текста. Операции сканирования индекса выполняются с буферным кэшем, тем самым решается проблема несоответствий зашифрованных данных. Кроме того, поскольку данные дешифруются и помещаются в буферный кэш только один раз (по крайней мере до их устаревания), дешифрование происходит только один раз, а не при каждом обращении к данным. Соответственно, в то время, пока данные остаются в SGA, шифрование не снижает производительность. Достигаются сразу обе цели — безопасность посредством шифрования и минимальное влияние на производительность. Итак, проблема решена, и с TTE отпадает надобность в пользовательских процедурах шифрования, приводившихся ранее? Вовсе нет!

При шифровании табличного пространства шифруются все объекты — индексы и таблицы, независимо от того, нужно их шифровать или нет, если вам потребовалось шифровать все данные в табличном пространстве или хотя бы их большинство. А если шифроваться должна лишь малая часть общего объема данных? С применением TTE на производительность вашего приложения будет влиять существенно больший объем данных, чем это действительно необходимо. База данных Oracle сокращает последствия шифрования, но не может полностью избежать их. В результате вам, может, все равно придется самостоятельно реализовать избирательное шифрование данных в таблицах своего приложения.

Кроме того, зашифрованные табличные пространства могут только создаваться; вы не сможете преобразовать существующее табличное пространство в зашифрованную форму (или шифрованное табличное пространство в обычное). Вместо этого придется создать зашифрованное табличное пространство и переместить в него объекты. При внедрении шифрования в существующую базу данных решение на базе TTE может оказаться неприемлемым из-за гигантских объемов многих рабочих баз данных. Пользовательское шифрование позволяет точно управлять тем, какие данные будут шифроваться (и дешифроваться) вашим приложением.

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

 

ШИФРОВАНИЕ И EXADATA

 

Вас заинтересует / Intresting for you:

Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 1462 просмотров Rasen Fasenger Mon, 22 Oct 2018, 04:44:08
Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 2166 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Работа с числами в PL/SQL на п...
Работа с числами в PL/SQL на п... 4526 просмотров Antoniy Mon, 28 May 2018, 16:45:11
Символьные функции и аргументы...
Символьные функции и аргументы... 3338 просмотров Анатолий Wed, 23 May 2018, 18:54:01

Comments on Шифрование в PL/SQL: уроки программирования

Будьте первым прокомментировавшим
Пожалуйста, авторизуйтесь, для комментирования