Цю сторінку перекладено машинним перекладом. Читайте англійський оригінал. English

Бібліотека IBSurgeon

Як працює шифрування бази даних Firebird

(c) Alexey Kovyazin, IBSurgeon, Alex Peshkoff, Firebird Project, 2021

Стаття заснована на матеріалах семінару «Шифрування баз даних» на конференції Firebird Conference 2019 у Берліні, Німеччина. У ній описується, як працює шифрування бази даних Firebird на рівні сервера та на стороні клієнта, як налаштувати шифрування бази даних, як використовувати його з різних типів застосунків (Delphi, Java, .NET). Приклади у статті базуються на IBSurgeon Firebird Encryption Framework (FEPF), але можуть бути адаптовані до більшості наявних реалізацій плагінів шифрування.

Зміст:

  1. Навіщо нам потрібне шифрування бази даних (і коли не потрібне)?
  2. Як працює шифрування бази даних Firebird на стороні сервера
  3. Яка частина бази даних шифрується?
  4. Коли сторінки даних шифруються?
  5. Як захистити передачу ключів?
  6. Як працює шифрування Firebird на стороні клієнта
  7. Нативні застосунки
  8. Java-застосунки
  9. .NET-застосунки
  10. Встановлення та налаштування
  11. Як відстежувати прогрес шифрування
  12. Підсумок

1. Навіщо нам потрібне шифрування бази даних (і коли не потрібне)?

Шифрування бази даних Firebird було представлено у версії Firebird 3.0 (разом із шифруванням протоколу передачі, яке часто плутають із обговорюваною темою) і значно розширило можливості захисту даних від несанкціонованого доступу. Однак це не панацея, і необхідно розуміти його сильні та слабкі сторони, щоб правильно ним користуватися.

У цій статті ми розглянемо внутрішні механізми шифрування бази даних на базовому рівні, щоб дати розробникам застосунків Firebird краще розуміння того, як працює шифрування бази даних.

Отже, навіщо нам потрібне шифрування бази даних?

  1. Для захисту баз даних із чутливими/цінними даними від «фізичного» викрадення. Якщо зловмисник викраде диск із копією зашифрованої бази даних або якимось чином отримає копію файлу бази даних, прочитати дані з неї без відповідного ключа буде неможливо, так само як і використати програмне забезпечення для відновлення, наприклад FirstAID, для вилучення даних. Звичайно, це залежить від алгоритму шифрування та обчислювальної потужності, але зламати AES256 потребуватиме занадто багато часу або занадто дорогих обчислювальних ресурсів.
  2. Для захисту бази даних від доступу неавторизованих застосунків без ключів шифрування. Прикладами є:
    • прямий доступ за допомогою інструменту розробника неавторизованою особою з метою зміни чутливої інформації (наприклад, грошових транзакцій),
    • зміна або викрадення бізнес-логіки (текстів збережених процедур і тригерів).
  3. Захист баз даних із попередньо заповненими даними від експорту до неавторизованих застосунків або доступу з них.
  4. Уряди нещодавно запровадили закони про захист даних (GDPR/DSVGO у Європі, LGPD у Бразилії тощо), які вимагають, серед іншого, вищого рівня захисту персональних та інших чутливих даних, і шифрування згадується як один із адекватних заходів захисту.

Коли шифрування бази даних не корисне?

У деяких випадках краще використовувати можливості безпеки та конфігурації Firebird замість шифрування бази даних:

  • Для захисту бази даних від фізичного доступу через мережу необхідно налаштувати мережевий доступ: тобто закрити спільні мережеві папки, оскільки Firebird не потребує спільного мережевого доступу до файлів бази даних, і посилити права безпеки (для Linux, наприклад, файли бази даних повинні мати доступ на читання-запис лише для користувача «firebird»).
  • Щоб обмежити доступ до конкретної бази даних для конкретної підмножини користувачів, простішим рішенням буде налаштування окремої бази даних безпеки.
  • Щоб обмежити доступ до об’єктів бази даних (таблиць, збережених процедур), необхідно використовувати механізми безпеки Firebird: користувачів, ролі тощо.

Звичайно, обидва списки вище неповні, але вони дають певне уявлення про те, коли потрібне або не потрібне шифрування бази даних.

2. Як працює шифрування бази даних Firebird на стороні сервера

Розглянемо внутрішні деталі шифрування бази даних Firebird, починаючи з серверної частини.

2.1. Яка частина бази даних шифрується?

Перше, що нам потрібно розглянути, - це те, яка частина бази даних шифрується? Як ви, напевно, знаєте, база даних Firebird складається з частин однакового розміру, які називаються «сторінками бази даних». Існує кілька типів таких сторінок, кожен тип служить певній меті.

Нижче ви можете побачити рисунок з основними типами даних:

Рисунок 1. Типи сторінок бази даних

Деякі сторінки призначені для зберігання даних користувачів, а інші потрібні для зберігання системної інформації, наприклад, сторінки транзакцій та інвентаризації сторінок (детальніше про сторінки бази даних доступно тут).

Коли база даних Firebird шифрується, шифруються лише сторінки з даними користувачів: сторінки даних, індекси, генератори та BLOB-об’єкти:

Рисунок 2. Шифруються лише сторінки бази даних із даними користувачів

Зверніть увагу, що метадані бази даних (збережені процедури, таблиці, представлення, тригери, назви генераторів тощо) не відрізняються від «даних користувачів» у частині рушія, відповідальної за шифрування, і вони шифруються.

Чому системні сторінки не шифруються? Здебільшого з міркувань продуктивності та через те, що вони не містять чутливих даних, які потребують захисту.

Сторінка заголовка бази даних не шифрується, оскільки вона містить інформацію, необхідну для шифрування (наприклад, назву ключа).

2.2. Коли сторінки даних шифруються?

Коли користувач виконує SELECT із зашифрованої бази даних, дані зчитуються із зашифрованого файлу, але надходять у сітку застосунку з результатами у незашифрованому вигляді.

Розглянемо деталі цього процесу:

Рисунок 3. Коли сторінки бази даних шифруються?

Зазвичай процес починається із серії зчитувань сторінок бази даних із файлу бази даних, і вони кешуються в кеші файлів операційної системи.

Firebird також можна налаштувати на обхід файлового кешу та використання лише власного кешу, але за замовчуванням використовується файловий кеш.

Після цього Firebird зчитує сторінки та поміщає їх у кеш сторінок Firebird (він визначається параметром DefaultDBCachePages у firebird.conf та/або databases.conf або на сторінці заголовка бази даних).

Потім сторінки з кешу вибираються до результуючого набору конкретного SQL-запиту (SELECT у нашому прикладі).

На рисунку нижче показано деталі:

Рисунок 4. Сторінки шифруються між кешем Firebird та файловим кешем ОС

Отже, сторінки бази даних шифруються у файловому кеші ОС, але надходять у кеш сторінок Firebird незашифрованими, і навпаки.

Частина програмного забезпечення Firebird, відповідальна за шифрування/дешифрування, називається «плагін шифрування». Оскільки більшість реалізацій плагінів (відомих авторам) називаються DbCrypt, ми будемо називати його DbCrypt.

На рисунку нижче ви можете побачити варіанти для Windows (DbCrypt.dll) та Linux (libDbCrypt.so):

Рисунок 5. Плагін шифрування (DbCrypt) виконує шифрування/дешифрування

Якщо ви достатньо довго подивитеся на цю картинку, наступне питання з’явиться досить швидко: як DbCrypt отримує відповідний ключ для шифрування/дешифрування сторінок бази даних?

Відповідь - існує ще один плагін для управління ключами.

Типова назва для управління ключами - KeyHolder, який служить сховищем/менеджером ключів для плагіна шифрування (DbCrypt). KeyHolder реалізує інтерфейс для управління ключами, який використовується DbCrypt.

Рисунок 6. DbCrypt та KeyHolder

Що означає «управління ключами»?

У найпростішому випадку DbCrypt може читати ключі з файлу на сервері. Файл може бути простим текстовим файлом, який можна сховати у «секретному» місці або на USB-флешці, або може бути зашифрованим файлом (наприклад, з використанням Windows Crypto API або з вбудованим внутрішнім ключем).

Файл ключів може містити кілька ключів, збережених для зручності у вигляді іменованого списку, і може виглядати так (приклад нижче взято з фреймворку плагінів шифрування IBSurgeon):

Code
Key=Red 0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,
Key=Green 0xab,0xd7,0x34,0x63,0xae,0x19,0x52,0x00,0xb8,0x84,0xa3,0x44,0xbd,0x11,0x9f,0x72,0xe0,0x04,0x68,0x4f,0xc4,0x89,0x3b,0x20,0x8d,0x2a,0xa7,0x07,0x32,0x3b,0x5e,0x74,

Коли база даних зашифрована, її сторінки заголовка залишаються незашифрованими, щоб зберігати інформацію про плагін шифрування та назву ключа, і ви можете побачити цю інформацію за допомогою команди “gstat -h databasename”:

Code
Database header page information:
....
Creation date    Jan 11, 2017 15:12:20
Attributes       force write, encrypted, plugin DBCRYPT

Variable header data:
 Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI=
 Key hash:       ask88tfWbinvC6b1JvS9Mfuh47c=
 Encryption key name:    RED
 Sweep interval:         0
*END*

DbCrypt може обробляти сторінки для кількох баз даних та кількох ключів:

Рисунок 7. Кілька ключів для кількох баз даних на одному сервері (тобто, екземплярі Firebird)

Вибір правильного ключа

Часто розробники ставлять питання: «Як плагін розпізнає, який ключ для якої бази даних?» Відповідь досить проста: за назвою ключа, яка зберігається на сторінці заголовка бази даних.

Рідше, але все ж важливе питання - що якщо назва ключа буде такою, як записано в заголовку, але значення ключа інше? Щоб запобігти помилкам читання сторінок через неправильний ключ, плагін DbCrypt зберігає зашифровану тестову послідовність (цифри 0…F) у заголовку, а потім, коли ключ активується, плагін намагається зашифрувати зразкові дані ключем і порівняти його хеш зі збереженим результатом, щоб переконатися, що передане значення ключа насправді правильне для цієї конкретної бази даних.

Підхід, коли плагін шифрування читає ключі безпосередньо, є простим і корисним для налагодження, тестів продуктивності тощо, оскільки він реалізує шифрування прозорим способом: тобто клієнтські застосунки та інструменти розробників не знають, що база даних зашифрована.

Однак насправді нам потрібно обмежити доступ застосунків до бази даних: лише клієнтський застосунок, який має ключ, повинен мати можливість підключитися до зашифрованої бази даних.

Для цього нам потрібен плагін KeyHolder, щоб отримати ключ від клієнтського застосунку (який зазвичай знаходиться на іншому комп’ютері) через мережевий протокол Firebird.

2.3. Як захистити передачу ключа?

Можливо, ми захочемо захистити базу даних у ситуації, коли клієнт вирішує отримати прямий доступ до зашифрованої бази даних, обходячи авторизовані застосунки (багато постачальників хочуть обмежити дані від прямого доступу, або лише для читання, або для читання-запису).

Це еквівалентно ситуації, коли зловмисник має доступ до сервера, але не має ключів.

Розглянемо наступні сценарії атак для перехоплення ключів на стороні сервера:

  1. Коли зловмисник створює підроблений плагін шифрування (DBCrypt.dll) і розміщує його на сервері, і коли KeyHolder передає ключ, підроблений DbCrypt робить дамп ключа:

Рисунок 8. Атака з підробленим DbCrypt.dll

  1. Коли зловмисник створює підроблений файл firebird.exe і робить дамп за його допомогою:

Рисунок 9. Атака з підробленим firebird.exe

Щоб захиститися від таких атак, хороша реалізація плагінів шифрування та управління ключами повинна захищати обмін ключами.

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

Ці ключі генеруються під час процесу збірки та вбудовуються для конкретної пари плагінів шифрування та управління ключами. Для найкращого захисту необхідно використовувати спеціально зібрані пари DbCrypt/KeyHolder.

Коли DbCrypt і KeyHolder обмінюються ключами, вони використовують наступний протокол (він спрощений, але ідея зрозуміла, я думаю):

Code
DbCrypt → KeyHolder:
	Дай мені ключ бази даних з цією сіллю
KeyHolder:
	Шифрує DbKey відкритим ключем, використовуючи сіль від DbCrypt
	Передає зашифрований DbKey до DbCrypt
DbCrypt:
	Розшифровує DbKey закритим ключем
	Перевіряє правильність солі
	Готовий до роботи

Більш-менш той самий протокол використовується для обміну ключами між екземплярами KeyHolder, а також для обміну ключами між клієнтським застосунком і KeyHolder.

Зверніть увагу, що шифрування та правильність переданих ключів залежать від реалізації плагіна, рушій Firebird надає лише базову низькорівневу службу передачі «надіслати N байтів від цього екземпляра плагіна до того екземпляра плагіна».

Підсумок для серверної частини шифрування

  • Шифрування/дешифрування виконується плагіном шифрування бази даних (DbCrypt), сторінка за сторінкою, під час обміну даними між файловим кешем операційної системи та кешем сторінок Firebird
  • Управління ключами може бути реалізоване простим способом, коли DbCrypt читає ключі безпосередньо, але зазвичай це робиться за допомогою плагіна управління ключами (KeyHolder)

Тепер давайте дізнаємося, як клієнтські застосунки працюють із зашифрованими базами даних.

3. Як працює шифрування Firebird на стороні клієнта

3.1. Нативні застосунки

Щоб зрозуміти, що відбувається, коли клієнтський застосунок підключається до зашифрованої бази даних, розглянемо звичайний процес підключення до незашифрованої бази даних для нативних застосунків.

Зверніть увагу: звідси і далі «нативний» означає, що такий застосунок встановлює мережеве з’єднання з сервером за допомогою fbclient.dll, зазвичай такий застосунок створений на Delphi, C++, PHP. На відміну від нативних застосунків, Java та .NET реалізують власну версію протоколу, вони будуть розглянуті нижче.

Процес підключення:

  1. Клієнтський застосунок завантажує клієнтську бібліотеку
  2. fbclient.dll - нативні застосунки Windows
  3. libfbclient.so - нативні застосунки Linux
  4. Клієнтський застосунок ініціює підключення, надсилаючи
  5. Ім’я користувача, напр., SYSDBA
  6. Пароль, напр., masterkey
  7. Шлях/аліас бази даних

У випадку зашифрованої бази даних потрібен додатковий крок: необхідно передати назву ключа шифрування та його значення.

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

Отже, це приводить нас до наступного:

  1. Додатковий мережевий обмін необхідний для передачі ключа перед звичайним підключенням
  2. Передача ключа від клієнтського застосунку до Firebird вимагає кодування з використанням асиметричного шифрування та реалізації інтерфейсу зворотного виклику, це може бути досить складно. Щоб спростити це завдання, постачальники плагінів надають приклад коду для підключення або, як у фреймворку плагінів IBSurgeon, створюють додаткову бібліотеку fbcrypt.dll/libfbcrypt.so, яка реалізує зручний для використання інтерфейс для передачі ключів від клієнтського застосунку.

Щоб підключити нативний застосунок (який використовує fbclient.dll) до зашифрованої бази даних, потрібно виконати 3 виклики. Нижче наведено приклад на Delphi (спрощений, без обробки помилок):

В обробнику події BeforeConnect:

Code
fbcrypt_init(PAnsiChar(‘C:\Firebird30.bclient.dll’));
fbcrypt_key(‘RED’, ‘0xec,0xa1,0x52,0xf6,...’));
fbcrypt_callback(nil);

 // Потім підключитися як зазвичай
Database1.Active:=True;

На рисунку нижче ви можете побачити огляд процесу підключення до зашифрованої бази даних у нативному застосунку:

Рисунок 10. Процес підключення до зашифрованої бази даних для нативних застосунків

А як щодо потокобезпечності у випадку багатопотокових клієнтських застосунків?

Дозвольте нагадати вам деякі загальні моменти реалізації багатопотокових клієнтських застосунків.

Починаючи з Firebird 2.5, кілька потоків усередині застосунку можуть безпечно використовувати єдине підключення до бази даних, оскільки вся необхідна синхронізація виконується всередині fbclient.dll.

Однак у цьому випадку потоки зможуть працювати з підключенням лише по черзі.

Це нормально для застосунків, які не потребують високопродуктивного обміну даними з базою даних - якщо не проблема зачекати виконання SQL-запиту з одного потоку, коли інший потік виконує інший SQL, простіше використовувати просту модель, коли 1 підключення спільне для кількох потоків.

Якщо застосунок потребує виконання SQL-запитів паралельно (тобто це повноцінний клієнтський застосунок), краще використовувати окремий потік для кожного підключення.

Ситуація з обміном ключами для підключень до зашифрованих баз даних є дещо складнішою.

При кожному підключенні клієнтська бібліотека передає ключі від клієнта, але це не пов’язано безпосередньо з потоками в клієнтському застосунку - ситуація залежить від використовуваного API.

Як відомо, клієнтська бібліотека Firebird починаючи з 3.0 пропонує 2 типи API: новий об’єктно-орієнтований API, заснований на концепції провайдерів, та застарілий isc_ API, реалізований як обхідний шлях для збереження сумісності зі старими драйверами Firebird.

Якщо використовується новий об’єктно-орієнтований клієнтський API, достатньо створити провайдера, надати йому необхідні ключі, а потім використовувати його для нових підключень.

Якщо використовується isc_ клієнтський API, для кожного підключення клієнтська бібліотека створить власного тимчасового провайдера, який не є безпосередньо видимим або доступним для кінцевого користувача.

У цьому випадку ключ передається саме з того потоку, де викликається isc_attach_database, і для зберігання цього ключа використовується локальне сховище потоку.

На практиці, оскільки майже всі клієнтські бібліотеки використовують isc_ API (на даний момент серед популярних драйверів лише Python-драйвер використовує OO API), необхідно викликати fb_database_crypt_callback() у кожному потоці, який підключається до зашифрованої бази даних.

Виклики передачі ключів (виклики fbcrypt.dll у прикладі FEPF) мають бути виконані перед підключенням, у тому ж потоці, де буде встановлено з’єднання.

Коли ми працюємо з багатьма базами даних (наприклад, SaaS веб-сервер з багатьма клієнтськими базами даних), важливо пам’ятати, що кожен виклик fbcrypt_key() додає ключ до сховища KeyHolder, пов’язаного з поточним підключенням.

Значення ключів мають бути встановлені перед підключенням; після встановлення з’єднання значення ключа не може бути змінено.

У разі від’єднання ключі не вивантажуються, вони зберігатимуться в пам’яті до вивантаження fbcrypt.dll.

3.2. Java-застосунки

Java-драйвер (JayBird) має власну реалізацію (на чистій Java) протоколу підключення Firebird. Jaybird 4 (та 3.0.4+) додає підтримку зворотних викликів шифрування бази даних Firebird 3 у чистій Java-реалізації протоколу версії 13.

З Jaybird 4 Readme:

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

Майбутні версії Jaybird (ймовірно, 5) введуть підтримку плагінів для плагінів шифрування бази даних, які потребують складнішого зворотного виклику.

Практично це означає, що нам потрібно встановити значення для зворотного виклику шифрування (зазвичай це ім’я ключа та пара ключ-значення) у властивості підключення dbCryptConfig.

Наприклад:

Code
 edConnectionString.setText("jdbc:firebirdsql://localhost/g:/Databases/ODS12/crypt.fdb?lc_ctype=utf8&dbCryptConfig=MyKey:0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,");

Також можна вказати рядок у base64 - з readme:

Рядки з префіксом base64:: решта рядка декодується як base64 у байти.

Символи заповнення = є необов’язковими, але якщо вони присутні, вони мають бути дійсними (тобто якщо ви використовуєте заповнення, ви повинні використовувати правильну кількість символів заповнення для довжини).

Коли значення, закодоване в base64, містить +, його потрібно екранувати як %2B у JDBC URL. Для зворотної сумісності з Jaybird 3 ми не можемо перейти на URL-безпечний варіант base64.

У реалізації IBSurgeon плагіна керування ключами така передача ключа вважається більш-менш небезпечною: якщо шифрування мережевого протоколу не ввімкнено ( до речі, щоб його ввімкнути, встановіть у firebird.conf WireCrypt=Required і не використовуйте застарілу автентифікацію), ключ можна легко виявити за допомогою аналізатора мережевого трафіку, наприклад WireShark. Отже, щоб увімкнути передачу ключів таким способом, необхідно встановити UnsafeClient=true у KeyHolder.conf плагіна керування ключами IBSurgeon.

3.3 .NET-застосунки

Провайдер Firebird.NET реалізує подібну схему обміну ключами для зашифрованих баз даних і також вимагає встановлення параметра UnsafeClient=true у KeyHolder.conf у FEPF.

Приклад .NET рядка підключення для зашифрованих баз даних:

Code
string connectionString =
                "User=SYSDBA;" +
                "Password=masterkey;" +
                "Database=G:\\Databases\\ODS12.RYPT.FDB;" +
                "DataSource=localhost;" +
                "Port=3053;" +
                "Dialect=3;" +
                "Charset=NONE;" +
                "Role=;" +
                "Connection lifetime=15;" +
                "Pooling=true;" +
                "MinPoolSize=0;" +
                "MaxPoolSize=50;" +
                "Packet Size=8192;" +
                "ServerType=0;" +
                 "cryptkey = TXlLZXk6MHhlYywweG…...;";

Ви можете помітити, що ключ шифрування виглядає інакше, ніж у прикладі для нативних застосунків та JayBird. Це тому, що це результат перетворення Base64. Отже, щоб отримати ключ для .NET або Java-застосунку, необхідно обчислити base64 з рядка:

“MyKey:0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,”

і використовувати його як параметр для “cryptkey=xxx;” з “;” в кінці рядка підключення.

4. Встановлення та налаштування

Щоб увімкнути шифрування бази даних і плагін керування ключами, необхідно вказати назву плагіна шифрування у файлі конфігурації Firebird firebird.conf:

Code
 KeyHolderPlugin = KeyHolder

Або, альтернативно, у databases.conf для аліаса зашифрованої бази даних:

Code
myencrypted = C:\Temp\EMPLOYEE30.MPLOYEE30.FDB { KeyHolderPlugin = KeyHolder }

Потім необхідно переконатися, що всі файли, необхідні для плагіна, знаходяться на сервері.

Приклад нижче наведено для FEPF від IBSurgeon, але інші плагіни більш-менш схожі:

у %FirebirdFolder$\plugins

Code
    • DbCrypt.dll
    • DbCrypt.conf
    • KeyHolder.dll
    • KeyHolder.conf - лише для режиму налагодження!
Code

**У %FirebirdFolder$**
• fbcrypt.dll
• libcrypto-1_1-x64.dll
• libssl-1_1-x64.dll
• firebird.msg
Code

Після цього ми можемо виконати тестове шифрування на сервері, для цього в isql:

isql.exe localhost:C:\Temp\EMPLOYEE30.MPLOYEE30.FDB -user SYSDBA -pass masterkey SQL>alter database encrypt with dbcrypt key red; SQL> show database; Database: localhost:C:\Temp\EMPLOYEE30.MPLOYEE30.FDB …. ODS = 12.0 Database encrypted Default Character set: NONE

Code

Якщо ви на Linux, пам'ятайте, що регістр має значення, тому команда буде:

alter database encrypt with “DbCrypt” key Red;

Code

Тепер ми можемо перевірити доступ клієнта до зашифрованої бази даних. Для цього ми видалимо (або перейменуємо, або відредагуємо) файл конфігурації KeyHolder.conf і спробуємо підключитися до зашифрованої бази даних за допомогою простого тестового застосунку.

Для цього ми повинні розмістити в папці з клієнтським застосунком наступні файли:

- Демо-застосунок з [FEPF](/uk/download-demo-firebird-encryption-plugin) - CryptTest.exe (32-бітний)
- Обов'язкові файли:
  - fbclient.dll
  - fbcrypt.dll
  - libcrypto-1.1.dll
  - libssl-1.1-x64.dll
- Необов'язкові файли:
  - firebird.conf
  - в plugins
  - ◦ KeyHolder.conf
  - ◦ keyhodler.dll

У деяких реалізаціях плагінів керування ключами можливо [завантажувати ключі в клієнтську бібліотеку](/uk/download-demo-firebird-encryption-plugin#Connect%20Firebird%20database%20with%20developer%20tools) (fbclient.dll) без модифікації клієнтського програмного забезпечення.

Це забезпечує прозору роботу інструментів розробників Firebird (таких як Firebird SQL Studio, DatabaseWorkbench, IBExpert, FlameRobin, RedExpert тощо) та прозоре використання інструментів командного рядка Firebird (gfix.exe, nbackup.exe тощо).

## 5. Як відстежувати прогрес шифрування

Firebird шифрує базу даних лише тоді, коли є активні з'єднання. Процес шифрування виконується в окремому паралельному потоці, і для великих баз даних повне шифрування може зайняти значний час.

Щоб відстежувати процес шифрування, виконайте SQL-запит із MON$:

select mon$crypt_page * 100.0 / mon$pages as Percent from mon$database; commit;

Code

або виконайте інструмент gstat зі спеціальним перемикачем:

gstat -e dbname

Database “D:\ENCDB\TESTENCRYPT.FDB” Gstat execution time Tue Mar 16 11:45:11 2021

Database header page information: Flags 0 Generation 10697 System Change Number 3 Page size 8192 ODS version 12.0 Oldest transaction 7053 Oldest active 7054 Oldest snapshot 7054 Next transaction 7054 Sequence number 0 Next attachment ID 17834 Implementation HW=Intel/i386 little-endian OS=Windows CC=MSVC Shadow count 0 Page buffers 0 Next header page 0 Database dialect 3 Creation date Oct 9, 2019 6:42:31 Attributes encrypted, plugin DBCRYPT

Variable header data:
    Database backup GUID:   {866B4967-ED58-427E-A481-DB9206CEA2ED}
    Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI=
    Key hash:       ask88tfWbinvC6b1JvS9Mfuh47c=
    Encryption key name:    RED
    Database GUID:  {323FE494-1771-4608-E99D-C1B69C84578B}
    *END*

Data pages: total 105, encrypted 105, non-crypted 0 Index pages: total 95, encrypted 95, non-crypted 0 Blob pages: total 0, encrypted 0, non-crypted 0 Generator pages: total 1, encrypted 1, non-crypted 0 Gstat completion time Tue Mar 16 11:45:11 2021

Code

Зверніть увагу, що виконання gstat може бути тривалим процесом.

## 6. Підсумок

1. Шифрування бази даних Firebird - це потужна функція для захисту інформації в базах даних від несанкціонованого доступу.
2. Процес шифрування вимагає серверної динамічної бібліотеки - плагіна шифрування (зазвичай називається DbCrypt), а в переважній більшості випадків - плагіна керування ключами (зазвичай називається KeyHolder).
3. Безпечна та надійна реалізація плагінів DbCrypt і KeyHolder має враховувати найпоширеніші типи атак.
4. Щоб працювати із зашифрованою базою даних, клієнтські застосунки повинні передавати ключ шифрування.
5. Встановлення та налаштування плагіна шифрування на сервері є тривіальним, воно вимагає 1 параметра у firebird.conf/databases.conf і кількох файлів.
6. Процес шифрування може бути тривалим, він виконується в окремому фоновому потоці, прогрес можна відстежувати за допомогою виклику MON$ або gstat.

### Що далі?

Ми працюємо над детальним тестом продуктивності шифрування бази даних Firebird. Загалом продуктивність знижується на 4-8%, але це залежить від апаратного забезпечення та налаштувань Firebird. Слідкуйте за оновленнями!

### Зв'яжіться з нами:

Будь ласка, надсилайте свої пропозиції, виправлення помилок, друкарські помилки тощо, а також будь-які запитання електронною поштою: [[email protected]](mailto:[email protected]?subject=Firebird%20Db%20encryption%20article)