Zbiory kluczy

Tink używa zestawów kluczy do włączania rotacji kluczy. Formalnie zbiór kluczy to niepusta lista1 kluczy, w których 1 klucz jest wyznaczony jako główny (klucz używany na przykład do podpisywania i szyfrowania nowych tekstów). Dodatkowo klucze w zestawie kluczy otrzymują unikalny identyfikator2 i stan klucza, który umożliwia wyłączenie kluczy bez usuwania ich z zestawu.

Zestawy kluczy to główne sposoby, za pomocą których użytkownicy mogą uzyskiwać dostęp do kluczy (za pomocą klasy KeysetHandle). Dzięki temu każdy użytkownik ma kod umożliwiający obsługę wielu kluczy jednocześnie. W przypadku większości użytkowników kryptografii konieczność jest możliwa: musi być możliwa zmiana kluczy (na przykład stare klucze mogą zostać ujawnione), a niemal nigdy nie ma możliwości atomowego „przełączenia się na następny klucz”, które można zastosować do maszyn uruchamianych przez kod i całego tekstu szyfrowania – globalnie i na bieżąco. Z tego względu użytkownik musi napisać kod, który będzie działać w przypadku zmiany klucza.

Przykład: AEAD

Rozważmy zestaw kluczy AEAD, który zawiera wiele kluczy dla elementu podstawowego AEAD. Jak wyjaśniliśmy wcześniej, każdy klucz jednoznacznie określa 2 funkcje: \(\mathrm{Enc}\) i \(\mathrm{Dec}\). Zestaw kluczy określa teraz także 2 nowe funkcje: \(\mathrm{Enc}\) oraz \(\mathrm{Dec}\) – \(\mathrm{Enc}\) po prostu równa się funkcji \(\mathrm{Enc}\) klucza podstawowego zestawu kluczy, natomiast funkcja \(\mathrm{Dec}\) próbuje odszyfrować wszystkie klucze, przechodząc przez nie w określonej kolejności (patrz poniżej, w którym Tink poprawia wydajność).

Warto zauważyć, że zestawy kluczy to pełne klucze – pełny opis funkcji \(\mathrm{Enc}\) i\(\mathrm{Dec}\) używanych. Oznacza to, że użytkownicy mogą napisać klasę, która wykorzystuje jako dane wejściowe KeysetHandle, podkreślając, że klasa potrzebuje pełnego opisu obiektów \(\mathrm{Enc}\) i \(\mathrm{Dec}\) do prawidłowego działania. Umożliwia to użytkownikom pisanie interfejsów API, które to komunikują: aby użyć tej klasy, musisz podać mi opis prymitywu kryptograficznego.

Rotacja kluczy

Wyobraźmy sobie użytkownika Tink, który pisze program, który najpierw uzyskuje zestaw kluczy z KMS, następnie tworzy obiekt AEAD z tego zbioru kluczy, a na koniec używa tego obiektu do szyfrowania i odszyfrowywania tekstów szyfrowania.

Taki użytkownik jest automatycznie przygotowany do rotacji klucza i przełączania algorytmów na wypadek, gdyby obecny wybór nie był już zgodny ze standardem.

Trzeba jednak zachować ostrożność podczas wdrażania takiej rotacji kluczy: najpierw KMS powinien dodać nowy klucz do zestawu kluczy (ale nie powinien jeszcze ustawić go jako podstawowego). Następnie nowy zestaw kluczy należy wdrożyć we wszystkich plikach binarnych, aby każdy plik binarny korzystający z tego zestawu miał najnowszy klucz. Dopiero wtedy nowy klucz powinien zostać ustawiony jako podstawowy, a powstały zestaw kluczy zostanie ponownie rozpowszechniony do wszystkich plików binarnych przy użyciu tego zestawu.

Kluczowe identyfikatory w tekstach zaszyfrowanych

Przeanalizuj jeszcze raz przykład zestawu kluczy AEAD. Jeśli odszyfrowanie tekstu zaszyfrowanego zostanie wykonane naiwnie, Tink będzie musiał(a) spróbować odszyfrować go wszystkimi kluczami z zestawu kluczy, ponieważ nie da się sprawdzić, który klucz został użyty do zaszyfrowania zestawu kluczy. Może to spowodować duże obciążenie wydajności.

Z tego powodu Tink pozwala na przedrostowanie tekstów zaszyfrowanych za pomocą 5-bajtowego ciągu pochodzącego z identyfikatora. Zgodnie z zasadą „Pełne klucze” ten prefiks jest częścią klucza i wszystkie teksty zaszyfrowane, które kiedykolwiek zostały wygenerowane za pomocą tego klucza, powinny mieć taki prefiks. Podczas tworzenia kluczy użytkownicy mogą wybrać, czy powinny one używać takiego prefiksu czy też używać formatu tekstu szyfrowanego bez tego prefiksu.

Jeśli klucz znajduje się w zestawie kluczy, Tink oblicza ten tag na podstawie identyfikatora klucza w zestawie. Unikalny identyfikator2 w zestawie kluczy oznacza, że tagi są niepowtarzalne. Z tego względu, jeśli używane są tylko klucze otagowane, nie można utracić wydajności w porównaniu z odszyfrowywaniem za pomocą jednego klucza. Podczas odszyfrowywania Tink musi wypróbować tylko jeden z kluczy.

Ponieważ jednak tag jest częścią klucza, oznacza to też, że może on znajdować się w zestawie kluczy tylko wtedy, gdy ma 1 konkretny identyfikator. Ma to pewne konsekwencje podczas opisywania implementacji kluczowych obiektów w różnych językach.


  1. Niektóre części Tink nadal traktują zestawy kluczy jako zestaw. Należy to jednak zmienić. Dzieje się tak dlatego, że kolejność ma znaczenie ogólne, np. weź pod uwagę typowy cykl życia rotacji klucza w Aead. Najpierw do zestawu kluczy jest dodawany nowy klucz. Ten klucz nie został jeszcze ustawiony jako podstawowy, ale jest aktywny. Ten nowy zestaw kluczy jest wdrażany dla wszystkich plików binarnych. Gdy wszystkie pliki binarne znają nowy klucz, staje się on podstawowym kluczem (tylko na tym etapie jego używanie jest bezpieczne tylko na tym etapie). W tym drugim kroku rotacja klucza musi znać ostatni dodany klucz. 

  2. Aby zapewnić zgodność z wewnętrzną biblioteką Google, Tink zezwala na stosowanie zestawów kluczy, w których identyfikatory są powtarzane. Ta obsługa zostanie wycofana w przyszłości.