Шифроване в MySQL: използване на Главен ключ

В навечерието на старта на новия набор курс «Бази данни» продължаваме с публикуването на серия статии за криптиране в MySQL.

Шифроване в MySQL: използване на Главен ключ

В предишната статия от тази серия (Шифроване в MySQL: ключови складове) разгледахме хранилищата на ключове. В тази статия ще обсъдим как се използва главния ключ (master key) и ще разгледаме предимствата и недостатъците на шифроването с метод на конвертите (envelope encryption). 

Идеята на шифроването на конверти е, че ключовете, използвани за шифроване (ключовете на табличните пространства), се шифроват с помощта на друг ключ (главният ключ). За шифроване на данни фактически се използват ключовете на табличните пространства. Графично това може да изглежда така:

Шифроване в MySQL: използване на Главен ключ

Главният ключ (master key) се намира в хранилището на ключове (keyring), а ключовете на табличните пространства — в заглавията на шифрованите таблични пространства (на страница 0 на табличното пространство). 

На изображението по-горе:

  • Таблица A е шифрована с ключ 1 (Key 1). Ключ 1 се шифрова с помощта на главния ключ (master key) и се съхранява в шифрован вид в заглавието на таблица A.

  • Таблица B е шифрована с ключ 2 (Key 2). Ключ 2 се шифрова с помощта на главния ключ (master key) и се съхранява в шифрован вид в заглавието на таблица B.

  • И така нататък.

Когато на сървъра му е необходимо да дешифрира таблица A, той получава главния ключ от хранилището, чете шифрования ключ 1 от заглавието на таблица A и дешифрира ключ 1. Дешифрираният ключ 1 се кешира в паметта на сървъра и се използва за дешифриране на таблица A.

InnoDB

В InnoDB фактическото шифроване и дешифриране се извършват на ниво вход-изход. Тоест, страницата се шифрова непосредствено преди да бъде записана на диска и се дешифрира веднага след четенето от диска.

В InnoDB шифроването работи само на ниво таблични пространства. И по подразбиране всички таблици се създават в отделни таблични пространства (file-per-table tablespace). Иначе казано, се създава таблично пространство, което може да съдържа само една таблица. Въпреки че можете да създавате таблици и в основното таблично пространство (general tablespace). Но във всеки случай таблицата винаги се намира в някакво таблично пространство. И тъй като шифроването се извършва на ниво таблично пространство, то е или напълно шифровано, или не. Тоест не можете в основното таблично пространство да шифровате само част от таблиците. 

Ако по някаква причина имате деактивирано file-per-table, всички таблици се създават в системното таблично пространство (system tablespace). В Percona Server for MySQL може да се шифрова системното таблично пространство с помощта на променливата innodbsystablespaceencrypt или чрез потоци за шифроване (encryption threads), но все още това е експериментална функция. В MySQL това не съществува.

Преди да продължим, трябва да разгледаме структурата на идентификатора на главния ключ (master key ID). Той се състои от UUID, KEYID и префикса „INNODBKey“. Изглежда така: INNODBKey-UUID-KEYID.

UUID — това е uuid на сървъра с шифрованото таблично пространство. KEYID — това е просто постоянно нарастваща стойност. При първоначалното създаване на главния ключ KEYID е равен на 1. При ротацията на ключа, когато се създава нов главен ключ, KEYID = 2 и т.н. По-подробно за ротацията на главните ключове ще говорим в следващите статии от тази поредица.

Сега, когато знаем как изглежда идентификаторът на главния ключ, нека погледнем заглавието на шифрованото таблично пространство. Когато табличното пространство е шифровано, информацията за шифроване се добавя към заглавието. Изглежда по следния начин:

Шифроване в MySQL: използване на Главен ключ

KEY ID — това е KEYID от идентификатора на главния ключ, който вече обсъдихме. UUID — това е uuid на сървъра, който също се използва в идентификатора на главния ключ. TABLESPACE KEY — ключът на табличното пространство, който се състои от 256 бита, случайно генерирани от сървъра. Инициализационният вектор (IV, initialization vector) също се състои от 256 случайно генерирани бита (въпреки че трябва да бъде 128 бита). IV се използва за инициализация на шифроването и дешифрирането на AES (от 256 бита се използват само 128). В края има контрольна сума CRC32 за TABLESPACE KEY и IV.

През цялото време малко опростявах, като казвах, че в заглавието има шифрован ключ на табличното пространство. Всъщност, ключът на табличното пространство и инициализационният вектор се съхраняват и шифроват заедно с помощта на главния ключ. Запомнете, че преди шифроването на ключа на табличното пространство и инициализационния вектор, за тях се изчислява CRC32.

Каква е ползата от CRC32?

Ако в две думи, за да се уверим в валидността на главния ключ. След дешифриране на ключа на табличното пространство и вектора на инициализация, се изчислява контролна сума и се сравнява с CRC32, съхраняван в заглавката. Ако контролните суми съвпадат, имаме правилен главен ключ и ключ на табличното пространство. В противен случай табличното пространство се отбелязва като отсъстващо (според нас, няма да можем да го дешифрираме).

Можете да попитате: в кой момент се извършва проверката на ключовете? Отговорът е — при стартиране на сървъра. Сървър с криптирани таблици / таблични пространства при стартиране прочита UUID, KEYID от заглавката и генерира идентификатор на главния ключ. След това получава необходимия главен ключ от хранилището (keyring), дешифрира ключа на табличното пространство и проверява контролната сума. Отново, ако контролната сума съвпада, всичко е наред, ако не — табличното пространство се отбелязва като отсъстващо.

Ако сте чели предишната статия от тази серия (Шифроване в MySQL: ключови складове), може би помните, че при използване на сървърно хранилище на ключове, при стартиране сървърът получава само списък с идентификатори на ключове, по-скоро key id и user id, тъй като тази двойка еднозначно идентифицира ключа. А сега казвам, че сървърът при стартиране получава всички ключове, необходими му за проверка на възможността за дешифриране на ключовете на табличните пространства. Защо тогава при инициализация, в случай на сървърно хранилище, се зареждат само keyid и userid, а не всички ключове? Защото не всички ключове може да са ви необходими. Основно това е свързано с ротацията на главния ключ. При ротация на главния ключ в хранилището се създава нов главен ключ, но старите ключове не се изтриват. Така че в сървърното хранилище на ключове можете да имате много ключове, които не са нужни на сървъра и следователно не се извличат при стартиране на сървъра.

Настъпи време да поговорим за предимствата и недостатъците на шифрирането с главен ключ. Най-голямото предимство е, че ви е нужен само един ключ за шифриране (главен ключ), който ще бъде съхраняван отделно от вашите шифрирани данни. Това прави стартирането на сървъра бързо, а съхранението малко, което улеснява управлението. Освен това, единственият главен ключ лесно може да бъде регенериран.

Въпреки това, шифрирането с главен ключ има един голям недостатък: след като пространството от таблици е шифрирано с tablespace_key, то винаги остава шифрирано с един и същи ключ. Ротацията на главния ключ тук не помага. Защо е недостатък? Знаем, че в MySQL има бъгове, които могат да доведат до внезапни сривове и създаване на core файл. Тъй като core файлът съдържа дамп на паметта на сървъра, може да се случи в дампа да бъде шифрираният ключ на пространството от таблици. Още по-лошо, дешифрираните ключове на пространството от таблици се съхраняват в памет, която може да бъде разменена на диск. Можете да кажете, че това не е недостатък, тъй като са ви нужни root права, за да получите достъп до тези файлове и до swap дяла. Да, но root разрешения са нужни само за кратко. След като някой получи достъп до дешифрирания ключ на пространството от таблици, той/тя може да продължи да го използва за дешифриране на данни дори и без root права. Освен това, дискът може да бъде откраднат, а swap дялът/core файловете могат да бъдат прочетени с помощта на външни инструменти. Целта на TDE е да го направи нечетим, дори ако дискът бъде откраднат. Percona Server for MySQL има възможност за повторно шифриране на пространството от таблици с новосгенерирани ключове. Тази функция се нарича потоци на шифриране (encryption threads) и към момента на писане на този текст все още е експериментална.

Научете повече за курса

Прочетете още:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster