Шифрование табличных пространств

Источник: oracle
Аруп Нанда

Автор: Аруп Нанда, член-директор Oracle ACE

Прозрачное шифрование табличных пространств не влияет на производительность.

В век, когда безопасность данных критична практически во всех видах бизнеса, базы данных очень важны. Они там, где самое ценное в жизни организации - номера кредитных карт, социальная секретная информация, имена и адреса - этот список можно продолжить. Риск утечки данных повышается, когда бизнес-данные выходят за пределы базы данных на лентах резервного копирования. Исторически эти ленты, попавшие за пределы организации, являлись источником воровства большого объёма данных. И из-за того, что такие ленты могут быть восстановлены на многих подобных машинах, злоумышленники могут свободно просматривать данные, а организация не способна защитить от них свои данные.

Как же предотвратить такие случаи? Простой ответ - шифрование: шифрование данных в базе и хранение ключа дешифрования в другом месте. Воры могут получить доступ к лентам резервного копирования и восстановить базу данных на другом сервере, но без ключа дешифрования они не смогут увидеть данные. Oracle представил прозрачное шифрование данных (transparent data encryption - TDE) столбцов в Oracle Advanced Security в Oracle Database 10g Release 2 (более подробно см. в статье "Transparent Data Encryption" в выпуске Oracle Magazine за сентябрь/октябрь 2005). Хотя эта возможность позволяет зашифровать столбцы таблицы без написания хотя бы одной строчки кода и помогает в нескольких ключевых вопросах безопасности, она может негативно влиять на производительность приложений, когда зашифрованный столбец используется при сканировании по диапазону или если он является внешним ключом. Шифрование столбцов выполняется прозрачно на уровне SQL базы данных, и индексы на зашифрованные столбцы строятся по зашифрованным значениям. Так как зашифрованные значения выглядят хаотично и бессмысленно, операции диапазонного сканирования по зашифрованным столбцам неэффективны. И хотя шифрование столбцов выполняется быстро, ограничение, связанное со сканированием диапазона, представляет собой реальную проблему во многих жизненных ситуациях.

Введение в TDE-зашифрованные табличные пространства

Опция Oracle Advanced Security в Oracle Database 11g представляет приятную новую возможность TDE -шифрование табличного пространства, которая позволяет зашифровать всё табличное пространство и поэтому учитывает ограничения при сканировании по диапазону и внешних ключей, имеющиеся при шифровании на уровне столбца. Новое табличное пространство создаётся как зашифрованное, и данные, как таблицы, так и индексы, хранятся зашифрованными в этом табличном пространстве, как показано на Рис. 1. Когда пользователь делает запрос по этим данным, серверный процесс перемещает данные из хранилища в буферный кэш и затем отдаёт сессии пользователя. Данные расшифровываются перед загрузкой в буферный кэш, поэтому внутри буферного кэша они всегда имеют исходный вид (расшифрованны). Так как все типы доступа к данным, включая сканирование индексов, соединение таблиц, и т.д., выполняются в буферном кэше, то производительность операций извлечения данных из зашифрованного табличного пространства не отличается от такого же извлечения данных из нормального, незашифрованного табличного пространства.

Шифрование требует наличия, по крайней мере, двух вещей: ключа и алгоритма шифрования. TDE использует так называемую двухуровневую архитектуру ключа: оба ключа шифрования, и столбца, и табличного пространства, хранятся в базе данных, но расшифровываются с помощью другого ключа, называемого основным ключом. Основной ключ хранится вне базы данных в специальном контейнере, который называется внешним модулем безопасности, и может легко устанавливаться, как Oracle wallet, или сложно, как аппаратное устройство модуля безопасности. Oracle wallet - это файл формата, соответствующего Public Key Cryptography Standard No. 12, и зашифровывается с использованием пароля. Для использования wallet, как модуля внешней безопасности, необходимо указать пароль, который позволит основному ключу получить доступ к базе данных. Если указать неправильный пароль, wallet не сможет открыться, и зашифрованные данные невозможно будет извлечь. Wallet автоматически закрывается, когда останавливается экземпляр базы данных, и должен быть открыт сотрудником безопасности, когда экземпляр запускается. Поэтому хотя злоумышленники могут восстановить базу данных с лент без wallet и пароля, они не смогут увидеть зашифрованные данные (в случае с аппаратным устройством модуля безопасности, аппаратное устройство должно иметь доступ к базе данных, описанный поставщиком устройства).


Рис. 1: Загрузка буферов с данными

При шифровании табличного пространства, перед тем, как буферы с данными будут записаны обратно на диск (как результат процесса установки контрольной точки), они зашифровываются процессами DB Writer (DBW), как показано на Рис. 2. Такие операции, как прямые вставки и чтение, которые манипулируют данными непосредственно в базе данных, выполняют шифрование в режиме он-лайн. Когда буферы журналов записаны процессом записи журнала (log writer), они также зашифровываются, поэтому исходные и последующие архивные журналы (archived redo logs) содержат только зашифрованные данные.


Рис. 2: Запись буферов из кэша на диск

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

Давайте посмотрим, как создать TDE-зашифрованное табличное пространство, используя файловый wallet. Заметим, что совместимость баз данных должна быть от 11.1 и выше. Сначала создаём wallet, если его ещё нет:

  1. Убедитесь, что переменная ORACLE_BASE установлена. Если она не установлена, установите ёе командой:
$ export ORACLE_BASE=/opt/oracle
  1. Перейдите в директорию ORACLE_BASE, а затем в поддиректорию этого экземпляра. В нашем случае экземпляр называется prolin1, поэтому я выполняю команду:
$ cd $ORACLE_BASE/admin/prolin1
  1. Создайте директорию с названием "wallet" для хранения wallet:
$ mkdir wallet
  1. Создайте wallet, указав ключ шифрования, желательно содержащий вперемешку цифры и буквы, например "T45rustMe54":
$ sqlplus / as sysdba
SQL> alter system set encryption key identified by "T45rustMe54";

Пароль чувствителен к регистру.

На предыдущем шаге wallet создаётся и открывается. Wallet необходимо создать только один раз. После того, как база данных будет открыта, wallet остаётся открытым до тех пор, пока либо он не будет явно закрыт, либо база данных остановлена, т.е. до того момента, когда wallet автоматически закрывается. Этот wallet можно открыть повторно после перезапуска базы данных с помощью команды:

SQL> alter system set wallet open identified by "T45rustMe54";
System altered.

Теперь, когда wallet установлен, можно создать зашифрованное табличное пространство.

1. Следующие команды создадут зашифрованное табличное пространство enc128_ts:

create tablespace enc128_ts
datafile '/u01/oracle/database/enc128_ts.dbf'
size 1M autoextend on next 1M encryption using 'AES128'
default storage (encrypt)
/

Обратите внимание на специальное выражение encryption using 'AES128", которое показывает, что используется алгоритм AES со 128-битным ключом. Можно использовать также значения AES192 и AES256 (вместо значения по умолчанию AES128) для 192- и 256-битных ключей соответственно.

2. Как только табличное пространство создано, в нём можно создавать объекты. Например, следующий код создаёт таблицу ACCOUNTS_ENC:

create table accounts_enc (
 ACC_NO NUMBER NOT NULL,
 FIRST_NAME VARCHAR2(30) NOT NULL,
... другие столбцы...
)
tablespace enc128_ts;

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

Чтобы убедиться в наличии шифрования, можно вставить запись со значением "David" в столбец FIRST_NAME и поискать это значение в файле данных табличного пространства enc128_ts:

SQL> insert into accounts_enc values (1, 'David' ,...);
$ strings enc128ts_ts.dbf / grep David

Эта команда ничего не покажет, потому что значение "David" было сохранено в зашифрованном табличном пространстве. Поиск явного значения не дал результатов, что и ожидалось (заметьте, что если искать строку в файле для незашифрованного табличного пространства, успешный поиск вернёт искомое значение из файла). Шифрование табличного пространства и производительность.

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

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

create tablespace normal_ts
datafile '/u01/oracle/database/normal_ts.dbf'
size 1M autoextend on next 1M;

Затем создадим две идентичные таблицы - ACCOUNTS_REG и ACCOUNTS_ENC - в табличных пространствах normal_ts и enc128_ts (зашифрованное табличное пространство, созданное ранее), соответственно, и одинаковым способом заполним таблицы. Создадим индекс по каждой из таблиц по столбцу FIRST_NAME. Код для создания таблиц и заполнения их данными см. в демонстрационном коде для этой статьи.

После загрузки данных выполняем запрос по одной из таблиц, ACCOUNTS_REG, чтобы найти все имена, начинающиеся на D. Этот запрос использует индекс по столбцу FIRST_NAME, как показано на Листинге 1. Затем выполняем тот же запрос, но заменяем ACCOUNTS_REG на ACCOUNTS_ENC, как показано на Листинге 2. Время выполнения запроса примерно одинаковое, как в случае с незашифрованным табличным пространством, так и в случае с зашифрованным, с одинаковым количеством извлечённых блоков в обоих случаях. Это показывает, что существенного ухудшения производительности при запросе по таблице из зашифрованного табличного пространства нет.

Листинг 1: Сканирование по индексу из незашифрованного табличного пространства

SQL> set autot on explain stat
SQL> set timing on
SQL> select first_name
 2 from accounts_reg
 3 where first_name like 'D%'
 4 /

 ... здесь строки... 

50161 rows selected.

Elapsed: 00:05:36.38

Execution Plan
---------------------------
Plan hash value: 966430551

---------------------------------------------------------------------------------
/ Id  / Operation        / Name         / Rows  / Bytes / Cost (%CPU)/ Time     /
---------------------------------------------------------------------------------
/   0 / SELECT STATEMENT /              /   210K/  1442K/  513    (1)/ 00:00:07 /
/*  1 /  INDEX RANGE SCAN/IN_ACC_REG_FN /   210K/  1442K/  513    (1)/ 00:00:07 /
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("FIRST_NAME" LIKE 'D%')
        filter("FIRST_NAME" LIKE 'D%')


Statistics
--------------------------------
           1  recursive calls
           0  db block gets
        3458  consistent gets
         127  physical reads
...

Листинг 2: Сканирование таблицы по индексу из зашифрованного табличного пространства

SQL> set autot on explain stat
SQL> set timing on
SQL> select first_name
 2 from accounts_enc
 3 where first_name like 'D%'
 4 /

 ... здесь строки... 

Elapsed: 00:05:33.85

Execution Plan
---------------------------
Plan hash value: 399953395

-----------------------------------------------------------------------------------
/ Id  / Operation         / Name          / Rows  / Bytes / Cost (%CPU)/ Time     /
-----------------------------------------------------------------------------------
/   0 / SELECT STATEMENT  /               /   210K/  1442K/   513   (1)/ 00:00:07 /
/*  1 /  INDEX RANGE SCAN / IN_ACC_ENC_FN /   210K/  1442K/   513   (1)/ 00:00:07 /
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("FIRST_NAME" LIKE 'D%')
        filter("FIRST_NAME" LIKE 'D%')


Statistics
--------------------------------
           1  recursive calls
           0  db block gets
        3427  consistent gets
         127  physical reads
...

Сравнение шифрования табличных пространств с шифрованием на уровне столбцов

TDE на уровне столбцов позволяет зашифровать данные только в специальных столбцах. Вот как зашифровывается столбец FIRST_NAME в таблице ACCOUNTS_REG_ENC, созданной на основе таблицы ACCOUNTS_REG:

create table accounts_reg_enc
nologging as
select * from accounts_reg;

alter table accounts_reg_enc
modify first_name encrypt using 'AES128'
no salt;

После этой модификации значения столбца FIRST_NAME будут храниться в таблице ACCOUNTS_REG_ENC зашифрованными. Все другие столбцы будут нормальными. Однако, так как блоки этой таблицы в буферном кэше - это репликация таблицы, то столбец FIRST_NAME будет в нём по-прежнему зашифрованным. А это существенно повлияет на производительность сканирования индекса по столбцу FIRST_NAME.

Давайте проверим, велико ли влияние, выполнив небольшой тест. Мы запросим данные из таблицы ACCOUNTS_REG_ ENC (которая в незашифрованном табличном пространстве, а столбец FIRST_NAME зашифрован). Найдём имена, начинающиеся на D, с помощью запроса по индексу. Мы повторим запрос по таблице ACCOUNTS_ENC (в зашифрованном табличном пространстве). Затем по производительности запроса узнаем, как повлиял зашифрованный столбец, применив команду autotrace on explain stat, которая показывает используемый план оптимизации, и статистику, такую как consistent gets. Листинг 3 показывает команды и результаты.

Листинг 3: Сравнение запросов при шифровании уровня столбца и уровня табличных пространств

/* Выполним запрос по таблице ACCOUNTS_REG_ENC (в незашифрованном табличном пространстве,*/
/* но с зашифрованным столбцом first_name): */

SQL> set autotrace on explain stat
SQL> set linesize 120
SQL> select count(1) from accounts_reg_enc
 2 where first_name like 'D%';

--------------------------------------------------------------------------------------------
/ Id  / Operation               / Name          / Rows   / Bytes   / Cost (%CPU)/ Time     /
--------------------------------------------------------------------------------------------
/   0 / SELECT STATEMENT        /               /      1 /       7 /   686   (5)/ 00:00:09 /
/   1 /  SORT AGGREGATE         /               /      1 /       7 /            /          /
/*  2 /     INDEX FAST FULL SCAN/ IN_ACC_REG_FN /  50000 /     341K/   686   (5)/ 00:00:09 /
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
--------------------------------------------------------
 
   2 - filter(INTERNAL_FUNCTION("FIRST_NAME") LIKE 'D%')
 

Statistics
--------------------------------
 0 recursive calls
 0 db block gets
 13963 consistent gets
...

/* Теперь выполним тот же запрос по таблице ACCOUNTS_ENC (в зашифрованном табличном пространстве): */

SQL> select count(1) from accounts_enc
 2 where first_name like 'D%';

-------------------------------------------------------------------------------------
/ Id  / Operation         / Name          / Rows  / Bytes  /  Cost (%CPU)/ Time     /
-------------------------------------------------------------------------------------
/   0 / SELECT STATEMENT  /               /     1 /      7 / 513      (1)/ 00:00:07 /
/   1 /  SORT AGGREGATE   /               /     1 /      7 /             /          /
/*  2 /   INDEX RANGE SCAN/ IN_ACC_ENC_FN /   210K/   1442K/ 513      (1)/ 00:00:07 /
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
----------------------------------------------------

 2 - access("FIRST_NAME" LIKE 'D%')
 filter("FIRST_NAME" LIKE 'D%')


Statistics
------------------------------
 0 recursive calls
 0 db block gets
 120 consistent gets
...

Рассмотрим различия. Путь доступа изменяется от INDEX FAST FULL SCAN для таблицы с зашифрованным столбцом (ACCOUNTS_REG_ENC) до INDEX RANGE SCAN для таблицы в зашифрованном табличном пространстве (ACCOUNTS_ENC), который показал уменьшение consistent gets от 13,963 до не более 120 - т.е. меньше, чем 1 процент от первого значения. Это означает, что запрос по таблице из зашифрованного табличного пространства выполняет только 1 процент логических операций ввода/вывода по сравнению с запросом по таблице с зашифрованным столбцом.

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

TDE-шифрование столбцов имеет дополнительные требования к хранению. Обычно зашифрованные значения больше, чем незашифрованные, что делает больше таблицу с зашифрованным столбцом. Чтобы проверить фактическое увеличение, можно использовать процедуру show_space, которая показывает объём таблиц - ACCOUNTS_REG (таблица в незашифрованном табличном пространстве), ACCOUNTS_ENC (эта таблица в зашифрованном табличном пространстве) и ACCOUNTS_REG_ENC (таблица ACCOUNTS_REG имеет только зашифрованный столбец FIRST_NAME). Листинг 4 показывает результат. Заметим, что потребление памяти (полных блоков) почти одинаково для обеих форм таблицы - как в незашифрованном, так и в зашифрованном табличных пространствах. Однако таблица в незашифрованном табличном пространстве с зашифрованным столбцом занимает примерно 15K полных блоков, по сравнению с 10K таблицы в зашифрованном табличном пространстве - около 50 процентов превышения. Поэтому при TDE-шифровании табличного пространства лучше не только производительность, но и нет заметного дополнительного потребления памяти, которое снижает производительность из-за увеличения I/O.

Листинг 4: Потребление памяти различными видами таблиц

SQL> set serveroutput on

SQL> exec show_space ('ACCOUNTS_REG','ARUP')
Unformatted Blocks...................... 0
FS1 Blocks (0-25)....................... 2
FS2 Blocks (25-50)...................... 0
FS3 Blocks (50-75)...................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks............................. 10,938
Total Blocks............................ 11,088
Total Bytes............................. 90,832,896
Total MBytes............................ 86
Unused Blocks........................... 1
Unused Bytes............................ 8,192
Last Used Ext FileId.................... 6
Last Used Ext BlockId................... 40,969
Last Used Block......................... 847

SQL> exec show_space ('ACCOUNTS_ENC','ARUP')
Unformatted Blocks..................... 0
FS1 Blocks (0-25)...................... 1
FS2 Blocks (25-50)..................... 0
FS3 Blocks (50-75)..................... 0
FS4 Blocks (75-100).................... 1
Full Blocks............................ 10,967
Total Blocks........................... 11,120
Total Bytes............................ 91,095,040
Total MBytes........................... 86
Unused Blocks.......................... 4
Unused Bytes........................... 32,768
Last Used Ext FileId................... 7
Last Used Ext BlockId.................. 10,249
Last Used Block........................ 876


SQL> exec show_space ('ACCOUNTS_REG_ENC','ARUP')
Unformatted Blocks..................... 0
FS1 Blocks (0-25)...................... 2
FS2 Blocks (25-50)..................... 0
FS3 Blocks (50-75)..................... 0
FS4 Blocks (75-100).................... 1
Full Blocks............................ 15,680
Total Blocks........................... 15,856
Total Bytes............................ 129,892,352
Total MBytes........................... 123
Unused Blocks.......................... 6
Unused Bytes........................... 49,152
Last Used Ext FileId................... 6
Last Used Ext BlockId.................. 29,705
Last Used Block........................ 490

Администрирование зашифрованных табличных пространств

Эта статья продемонстрировала, как использовать командную строку для создания зашифрованных табличных пространств, но зашифрованное табличное пространство можно также создать через Oracle Enterprise Manager. Чтобы создать зашифрованное табличное пространство через Oracle Enterprise Manager, на основной странице Database выберите закладку Server и нажмите ссылку Tablespaces под Storage. На этой странице нажмите Create, которая откроет окно, показанное на Рис. 3. Включите Encryption, и нажмите Encryption Options. Откроется новое окно, в котором можно указать алгоритм шифрования.


Рис 3: Создание зашифрованного табличного пространства в Oracle Enterprise Manager

Различные представления базы данных помогают управлять зашифрованными табличными пространствами по номеру табличного пространства, алгоритму шифрования и наличию шифрования. Столбец ENCRYPTED в представлении DBA_TABLESPACES словаря базы данных показывает, было ли табличное пространство зашифровано (YES или NO). Если табличное пространство зашифровано, соответствующая информация показана в другом представлении: V$ENCRYPTED_TABLESPACES. Представление V$ENCRYPTED_TABLESPACES имеет следующие столбцы:

  • TS#. Номер табличного пространства
  • ENCRYPTIONALG. Алгоритм шифрования, такой как AES128
  • ENCRYPTEDTS. Показывает, зашифровано ли табличное пространство (возможные значения YES и NO)

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

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

Заключение

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

Прозрачное шифрование табличного пространства - это пример возможности, которая позволяет не только получить кекс, но и съесть его.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=21549