Podstawowe elementy i interfejsy

Następnie definiujemy (informatywnie, ale bardziej formalnie) dwa ważne elementy języka Tink: primitive i Interface.

Podstawowe

Obiekt podstawowy to obiekt matematyczny odpowiadający wszystkim algorytmom, który bezpiecznie wykonuje niektóre zadania. Na przykład prymityw AEAD składa się ze wszystkich algorytmów szyfrowania, które spełniają właściwości zabezpieczeń wymagane przez Tink.

Podkreślamy, że elementy podstawowe nie są powiązane z językiem programowania ani z konkretnym sposobem dostępu do nich. Należy je traktować jako obiekt czysto matematyczny. Na przykład jeśli weźmiemy pod uwagę AEAD, zasadniczo będzie on składał się z par funkcji – jedna wykonuje szyfrowanie, i która umożliwia odszyfrowywanie.

Interfejsy

Interfejs to sposób, w jaki umożliwiamy użytkownikom dostęp do obiektu podstawowego. Spodziewamy się na przykład, że w przyszłości Tink będzie udostępniać interfejs Mac, ale także interfejs StreamingMac, który umożliwia obliczanie komputera Mac z danymi, które nie są ładowane bezpośrednio do pamięci.

Należy zauważyć, że w tym przypadku wyraźnie rozróżniamy interfejsy i elementy podstawowe. Powinno to wyraźnie wskazywać, że obiekt matematyczny, do którego dostęp dają te 2 interfejsy, jest taki sam.

Formalne definicje

Dla większości czytelników powinny wystarczyć powyższe, intuicyjne wyjaśnienia. Uważamy jednak, że niekiedy warto podać formalne definicje tych pojęć.

Funkcje kryptograficzne

Pojęcie funkcji kryptograficznej nie jest tak ważne jak jej pojęcie, ale musimy ją wprowadzić, aby formalnie zdefiniować prymitywną.

Funkcja kryptograficzna

Funkcja kryptograficzna to mapa

\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]

ze zbioru \({\bf K}\) (przestrzeń kluczy), ze zbioru \({\bf R} = \{0,1\}^{\infty}\)(przypadek losowości, w którym zakładamy, że jest to zbiór nieskończonych ciągów znaków) i z zestawu \({\bf I}\) (przestrzeń wejściowa) do zbioru \({\bf O}\) (przestrzeń wyjściowa).

Później stanie się jasne, dlaczego dodaliśmy określony parametr losowości.

Na przykład pokazujemy, jak można zmapować te koncepcje na AES-GCM. Dla każdego prawidłowego rozmiaru klucza ( \(s_k\)), liczby jednorazowej \(s_n\)i rozmiaru tagu\(s_t\)AES-GCM składa się z 2 funkcji kryptograficznych: jednej do szyfrowania i jednej do odszyfrowywania. Oba będą mieć tę samą spację klucza \({\bf K} = \{0,1\}^{s_k}\).

W przypadku funkcji szyfrowania \(\mathrm{Enc}\)do wybrania liczby jednorazowej używane są pierwsze \(s_n\) bity losowości.

Niech \({\bf B} = \{0,1\}^8\) oznacza bajt. Przestrzeń wejściowa funkcji szyfrowania to pary \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) par ciągów bajtów o dowolnej długości. Pierwszym elementem pary jest przekaz, a drugi – powiązane dane. Standard AES-GCM ogranicza długość danych wejściowych, ale wolimy zezwalać na dowolne długości i zamiast tego dajemy w przestrzeni wyjściowej specjalny symbol błędu \(\bot\) . Przestrzeń wyjściowa staje się wtedy \({\bf O} = {\bf B}^* \cup \{\bot\}\), gdzie dowolny wynik udanych obliczeń definiujemy jako konkatenację \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) zgodnie ze standardem i\(\bot\)na wypadek, gdyby niektóre dane wejściowe były za długie. Z tego względu w przypadku stałego klucza funkcja szyfrowania zmienia się na \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\).

W przypadku funkcji odszyfrowywania \(\mathrm{Dec}\) przestrzeń kluczy jest taka sama. Przestrzeń wejściowa jest przypadkowo taka sama: \({\bf I} ={\bf B}^* \times {\bf B}^*\), ale teraz pierwszy element ma być danymi wyjściowymi funkcji szyfrowania, a drugi nadal jest danymi powiązanymi.

Przestrzeń wyjściowa też jest taka sama \({\bf O} = {\bf B}^* \cup \{\bot\}\) (ponownie przez przypadek). Interpretacja jest nieco inna, ponieważ \(\bot\) zwykle oznacza błąd uwierzytelniania (choć takie dane będą też wyświetlane na wypadek, gdyby niektóre dane wejściowe były zbyt długie).

Podkreślamy, że taka formalizacja nie jest jedyną opcją sformalizowania standardu. Na przykład można uznać liczbę jednorazową za część danych wejściowych, zamiast odczytywać ją na podstawie losowości (co daje zupełnie inny element podstawowy). Dane wyjściowe można też zdefiniować jako potrójną wartość zawierającą liczbę jednorazową, tekst szyfrowany i tag (zamiast konkatenacji). Można też ograniczyć przestrzeń klucza (trochę według własnego uznania) do zakresu\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\).

Algorytm kryptograficzny:

(symetryczny) algorytm kryptograficzny to krotka

\[(f_1, ... f_k)\]

funkcji kryptograficznych, gdzie wszystkie funkcje mają tę samą przestrzeń klucza. Typem algorytmu kryptograficznego jest krotka \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\).

Na przykład dla każdego prawidłowego potrójnego \((s_k, s_n, s_t)\) klucza, liczby jednorazowej i rozmiaru tagu AES-GCM\({}_{s_k, s_n, s_t}\) to algorytm kryptograficzny z 2 funkcjami \(\mathrm{Enc}\) i \(\mathrm{Dec}\) opisanym powyżej.

Podstawowe elementy i interfejsy

Następnie definiujemy prymityw kryptograficzny.

Podstawowe
Etap prymitywny to zestaw algorytmów kryptograficznych, w których wszystkie algorytmy mają ten sam typ \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\), a przestrzenie kluczy w algorytmach są rozmieszczone w sposób rozłączny.

Weźmy na przykład element podstawowy \(\mathrm{AEAD}\) w Tink. Ma wiele algorytmów, między innymi AES-GCM dla kluczy o rozmiarze 128 i 256 bitów, z liczbą jednorazową o rozmiarze 96-bitowym, AES-EAX z niektórymi rozmiarami kluczy i XChaCha20Poly1305. Obejmują one rozłączone przestrzenie kluczy, ale wszystkie pełnią te same funkcje kryptograficzne\(\mathrm{Enc}\) i \(\mathrm{Dec}\). (Nie widzimy celu w jakiś sposób kompilacji różnych kluczowych rozmiarów AES-GCM w tej formalnej dyskusji, ale oczywiście jest to możliwe).

Definiowanie elementów podstawowych

Podstawowym sposobem myślenia o elementach podstawowych jest najpierw zdefiniowanie właściwości funkcji kryptograficznych, a potem po prostu określenie elementu podstawowego jako całości takich algorytmów.

Na przykład w przypadku AEAD uznamy, że \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) spełniono „zawsze” (z wyjątkiem sytuacji, gdy tekst jawny \(m\) jest zbyt długi). Mają też właściwości zabezpieczeń, np. w przypadku klucza losowego szyfrowanie jest bezpieczne semantycznie.

Obiekt podstawowy AEAD jest wtedy po prostu zbiorem wszystkich algorytmów kryptograficznych, które spełniają te właściwości. Innymi słowy, w praktyce gdy definiujemy określony element podstawowy, definiujemy go na podstawie właściwości. Nie podajemy listy algorytmów, jak sugeruje to definicja.

Interfejsy

Interfejs w Tink pozwala na dostęp do obiektów podstawowych w tym sensie, że umożliwia obliczanie elementu przestrzeni wyjściowej z przestrzeni wejściowej. Rozważmy na przykład interfejs AEAD w Javie:

public interface Aead {
  byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
  byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}

Pamiętaj, że nie przyznajemy dostępu do losowości. Zamiast tego pozwalamy użytkownikowi udostępniać elementy przestrzeni wejściowej. Odmowa dostępu do losowości jest oczywiście celowa1.

Tink czasami oferuje wiele interfejsów dla jednego obiektu podstawowego. Może to być bardzo przydatne, ponieważ wymagania mogą się czasem różnić. Jednak ogólnie rzecz biorąc, im więcej interfejsów oferuje dany interfejs, tym niższa interoperacyjność. Wyobraź sobie na przykład, że ktoś pisze w Tink bibliotekę, która wymaga od użytkownika przekazania obiektu Aead (aby zaszyfrować dane wewnętrznie). Jeśli Tink oferuje zbyt wiele różnych interfejsów na poziomie elementu podstawowego \(\mathrm{AEAD}\) , istnieje duże prawdopodobieństwo, że użytkownik nie ma gotowej instancji, która działa jednocześnie z wybranym przez użytkownika kluczem i biblioteką. W związku z tym dodawanie większej liczby interfejsów nie jest już rozwiązaniem.


  1. Mechanizmy szyfr AEAD mają właściwość zabezpieczoną przed wybranymi atakami wykorzystującymi tekst szyfrowany, co jest gwarantowane tylko wtedy, gdy nie ma możliwości ponownego użycia tych elementów. Interfejs Aead w Tink zapobiega ponownemu użyciu liczby jednorazowej: użytkownik nie może podać jako danych wejściowych liczby jednorazowej na potrzeby szyfrowania. W takiej sytuacji losowo generowana jest nowa wartość jednorazowa dla każdej operacji szyfrowania.