W przededniu nowego naboru na kurs kontynuujemy publikację serii artykułów na temat szyfrowania w MySQL.

W poprzednim artykule tej serii () omówiliśmy magazyny kluczy. W tym artykule przyjrzymy się, jak wykorzystywany jest klucz główny (master key), a także omówimy zalety i wady szyfrowania metodą kopertową (envelope encryption).
Idea szyfrowania kopertowego polega na tym, że klucze używane do szyfrowania (klucze przestrzeni tabel) są szyfrowane innym kluczem (kluczem głównym, master key). Klucze przestrzeni tabel są faktycznie używane do szyfrowania danych. Można to graficznie przedstawić w ten sposób:

Główny klucz (master key) znajduje się w magazynie kluczy (keyring), a klucze przestrzeni tabel — w nagłówkach zaszyfrowanych przestrzeni tabel (na stronie 0 przestrzeni tabel).
Na powyższym rysunku:
Tabela A jest szyfrowana kluczem 1 (Key 1). Klucz 1 jest szyfrowany za pomocą klucza głównego (master key) i przechowywany w postaci zaszyfrowanej w nagłówku tabeli A.
Tabela B jest szyfrowana kluczem 2 (Key 2). Klucz 2 jest szyfrowany za pomocą klucza głównego (master key) i przechowywany w postaci zaszyfrowanej w nagłówku tabeli B.
I tak dalej.
Gdy serwer musi odszyfrować tabelę A, pobiera klucz główny z magazynu, odczytuje zaszyfrowany klucz 1 z nagłówka tabeli A i odszyfrowuje klucz 1. Odszyfrowany klucz 1 jest przechowywany w pamięci serwera i używany do odszyfrowania tabeli A.
InnoDB
W InnoDB faktyczne szyfrowanie i deszyfrowanie odbywa się na poziomie wejścia-wyjścia. Oznacza to, że strona jest szyfrowana bezpośrednio przed zapisaniem na dysku i odszyfrowywana natychmiast po odczycie z dysku.
W InnoDB szyfrowanie działa tylko na poziomie przestrzeni tabel. Domyślnie wszystkie tabele są tworzone w oddzielnych przestrzeniach tabel (). Mówiąc inaczej, tworzona jest przestrzeń tabel, która może zawierać tylko jedną tabelę. Chociaż możesz również tworzyć tabele w głównej przestrzeni tabel (). W każdym razie tabela zawsze znajduje się w jakiejś przestrzeni tabel. I ponieważ szyfrowanie odbywa się na poziomie przestrzeni tabel, jest ono całkowicie szyfrowane lub nie. Oznacza to, że nie można zaszyfrować tylko części tabel w głównej przestrzeni tabel.
Jeśli z jakiegoś powodu masz wyłączoną opcję file-per-table, wszystkie tabele są tworzone wewnątrz systemowej przestrzeni tabel (system tablespace). W można zaszyfrować systemową przestrzeń tabel z wykorzystaniem zmiennej innodbsystablespaceencrypt lub korzystając z wątków szyfrowania (encryption threads), ale to wciąż jest funkcjonalność eksperymentalna. W MySQL tego nie ma.
Zanim przejdziemy dalej, musimy omówić strukturę identyfikatora głównego klucza (master key ID). Składa się on z UUID, KEYID oraz prefiksu „INNODBKey”. Wygląda to tak: INNODBKey-UUID-KEYID.
UUID to uuid serwera z zaszyfrowaną przestrzenią tabel. KEYID to po prostu stale rosnąca wartość. Przy początkowym tworzeniu głównego klucza KEYID wynosi 1. Przy rotacji klucza, gdy tworzony jest nowy główny klucz, KEYID = 2 itd. Szczegółowo na temat rotacji głównych kluczy porozmawiamy w kolejnych artykułach tej serii.
Teraz, gdy wiemy, jak wygląda identyfikator głównego klucza, przyjrzyjmy się nagłówkowi zaszyfrowanej przestrzeni tabel. Kiedy przestrzeń tabel jest szyfrowana, informacja o szyfrowaniu jest dodawana do nagłówka. Wygląda to następująco:

KEY ID to KEYID z identyfikatora głównego klucza, który już omówiliśmy. UUID to uuid serwera, który jest również używany w identyfikatorze głównego klucza. TABLESPACE KEY to klucz przestrzeni tabel, który składa się z 256 losowo wygenerowanych bitów przez serwer. Wektor inicjalizacji (IV, initialization vector) również składa się z 256 losowo wygenerowanych bitów (choć powinien mieć 128 bitów). IV jest używane do inicjacji szyfrowania i deszyfrowania AES (z 256 bitów wykorzystywanych jest tylko 128). Na końcu znajduje się suma kontrolna CRC32 dla TABLESPACE KEY i IV.
Przez cały ten czas nieco upraszczałem, mówiąc, że w nagłówku znajduje się zaszyfrowany klucz przestrzeni tabel. W rzeczywistości klucz przestrzeni tabel i wektor inicjalizacji są przechowywane i szyfrowane razem za pomocą głównego klucza. Pamiętaj, że przed zaszyfrowaniem klucza przestrzeni tabel i wektora inicjalizacji obliczana jest CRC32.
Po co potrzebna jest CRC32?
Krótko mówiąc, aby upewnić się o ważności głównego klucza. Po odszyfrowaniu klucza przestrzeni tabel i wektora inicjalizacji, obliczana jest suma kontrolna i porównywana z CRC32, przechowywaną w nagłówku. Jeśli sumy kontrolne się zgadzają, mamy prawidłowy główny klucz i klucz przestrzeni tabel. W przeciwnym razie przestrzeń tabel jest oznaczana jako nieobecna (i tak nie będziemy mogli jej odszyfrować).
Możesz zapytać: w którym momencie następuje sprawdzenie kluczy? Odpowiedź — podczas uruchamiania serwera. Serwer z zaszyfrowanymi tabelami / przestrzeniami tabel przy starcie odczytuje UUID, KEYID z nagłówka i generuje identyfikator głównego klucza. Następnie uzyskuje potrzebny główny klucz z magazynu (keyring), odszyfrowuje klucz przestrzeni tabel i sprawdza sumę kontrolną. Jeszcze raz, jeśli suma kontrolna się zgadza, wszystko jest w porządku, jeśli nie — przestrzeń tabel jest oznaczana jako nieobecna.
Jeśli czytałeś poprzedni artykuł z tej serii (), być może pamiętasz, że podczas korzystania z serwerowego magazynu kluczy, serwer przy uruchomieniu otrzymuje tylko listę identyfikatorów kluczy, a dokładniej, key id i user id, ponieważ ta para jednoznacznie identyfikuje klucz. A teraz mówię, że serwer przy uruchomieniu otrzymuje wszystkie klucze, które są mu potrzebne do sprawdzenia możliwości odszyfrowania kluczy przestrzeni tabel. Dlaczego więc podczas inicjalizacji, w przypadku serwerowego magazynu, ładowane są tylko keyid i userid, a nie wszystkie klucze? Ponieważ nie wszystkie klucze mogą być potrzebne. Głównie wiąże się to z rotacją głównego klucza. Przy rotacji głównego klucza w magazynie tworzony jest nowy główny klucz, ale stare klucze nie są usuwane. W ten sposób w serwerowym magazynie kluczy może znajdować się wiele kluczy, które nie są potrzebne serwerowi i, w związku z tym, nie są pobierane podczas uruchamiania serwera.
Nadszedł czas, aby porozmawiać o zaletach i wadach szyfrowania z użyciem klucza głównego. Największą zaletą jest to, że potrzebujesz tylko jednego klucza szyfrowania (klucza głównego), który zostanie przechowany oddzielnie od Twoich zaszyfrowanych danych. Ułatwia to szybkie uruchamianie serwera i zmniejsza potrzebne miejsce do przechowywania, co z kolei ułatwia zarządzanie. Ponadto jedyny klucz główny można łatwo regenerować.
Jednak szyfrowanie za pomocą klucza głównego ma jedną istotną wadę: po zaszyfrowaniu przestrzeni tabeli za pomocą klucza tablespace_key, zawsze pozostaje ona zaszyfrowana tym samym kluczem. Rotacja klucza głównego nie pomaga w tej sytuacji. Dlaczego to jest wada? Wiemy, że w MySQL występują błędy, które mogą prowadzić do nagłej awarii i stworzenia pliku core. Ponieważ plik core zawiera zrzut pamięci serwera, może się zdarzyć, że w zrzucie znajdzie się odszyfrowany klucz przestrzeni tabeli. Co gorsza, odszyfrowane klucze przestrzeni tabeli są przechowywane w pamięci, która może zostać swapowana na dysk. Możesz powiedzieć, że to nie jest wada, ponieważ potrzebne są uprawnienia root, aby uzyskać dostęp do tych plików i partycji swap. Tak, ale uprawnienia root są potrzebne tylko przez chwilę. Gdy ktoś uzyska dostęp do odszyfrowanego klucza przestrzeni tabeli, ta osoba może go dalej używać do odszyfrowania danych nawet bez uprawnień root. Ponadto dysk może zostać skradziony, a partycję swap lub pliki core można odczytać za pomocą programów firm trzecich. Celem TDE jest to, aby stało się to nieczytelne, nawet jeśli dysk zostanie skradziony. istnieje możliwość ponownego szyfrowania przestrzeni tabeli nowo wygenerowanymi kluczami. Funkcjonalność ta nazywa się wątkami szyfrowania (encryption threads) i w momencie pisania tego artykułu nadal jest eksperymentalna.
Czytaj dalej:
Źródło: habr.com
