В простейшем определении шифрование представляет собой «маскировку» данных, или их преобразование, при котором данные не могут использоваться посторонними. Рассмотрим очень простой пример: я ежедневно снимаю деньги со своего счета при помощи кредитной карты. Каждый раз я должен ввести в банкомате свой
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
; для всех остальных типов данных используйте функцию. Не забудьте преобразовать значения в формат RAW
(а CLOB
— вBLOB
), прежде чем передавать их функцииENCRYPT
.
SecureFiles
Большие объекты (LOB
) были значительно переработаны в Oracle Database 11g
; теперь для их обозначения используется термин SecureFiles
. Традиционные объекты LOB
(теперь называемые BasicFiles
), такие как CLOB
и BLOB
, по-прежнему доступны, но я не рекомендую их использовать. В любых ситуациях, в которых в прошлом использовалисьLOB
, теперь следует использовать SecureFiles
. Технология SecureFiles
предоставляет ту же функциональность, что и LOB
, а также ряд дополнительных возможностей — таких, как сжатие, устранение дубликатов, кэширование, возможность прекращения ведения журнала и т. д.
Дешифрование данных
Шифрование данных имеет смысл только в том случае, если зашифрованные данные в какой-то момент будут прочитаны и использованы в приложении. Эта задача решается при помощи функции 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-2
— SHA256
, 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
может оказаться неприемлемым из-за гигантских объемов многих рабочих баз данных. Пользовательское шифрование позволяет точно управлять тем, какие данные будут шифроваться (и дешифроваться) вашим приложением.
Безусловно, пользовательская реализация шифрования находит свое место в реальных приложениях. Прозрачное шифрование табличного пространства реализуется намного быстрее и проще, но вы должны убедиться в том, что «тотальное» шифрование, основанное на методе «грубой силы», подходит для вашего приложения.