Niech najpierw zidentyfikować zestaw możliwych problemów, a następnie starają się go rozwiązać. Mamy dane (rekord) i podpis. Podpis można obliczyć za pomocą różnych algorytmów. Program może ewoluować i zmieniać swoje zachowanie, libsodium może również (niezależnie) ewoluować i zmieniać swoje zachowanie. Na froncie generacji podpis mamy:
crypto_sign()
, który wykorzystuje pewne domyślny algorytm produkować podpisów (w chwili pisania tego tekstu jest po prostu wywołuje crypto_sign_ed25519()
)
crypto_sign_ed25519()
, która produkuje podpisów w oparciu o konkretne ed25519
algorytmu
Zakładam, że dla jednego konkretnego algorytmu z tymi samymi danymi wejściowymi i tym samym kluczem zawsze otrzymamy ten sam wynik, ponieważ jego matematyka i każde odchylenie od tej reguły spowoduje, że biblioteka będzie całkowicie bezużyteczna.
Rzućmy okiem na dwóch głównych opcji:
- Korzystanie
crypto_sign_ed25519()
cały czas i nigdy nie zmienia tego. Nie jest tak źle z opcji, ponieważ jest prosta i tak długo, jak crypto_sign_ed25519()
istnieje w libsodium i jest stabilna w swoim wyjściu, nie musisz się martwić stabilnym sygnaturą o stałym rozmiarze i zerowym narzutem zarządzania dla tego. Oczywiście, w przyszłości ktoś może odkryć jakiś straszny problem z tym algorytmem i jeśli nie jesteś przygotowany na zmianę algorytmu, który może oznaczać dla ciebie okropny problem.
- Korzystanie z
crypto_sign()
. Dzięki temu nagle mamy wiele problemów, ponieważ algorytm może się zmienić, więc musisz przechowywać niektóre metadane wraz z podpisem, co otwiera zestaw pytań:
- co do sklepu?
- czy te metadane mają być na poziomie rekordu lub pliku?
Co mamy w wymienionych funkcji za drugim podejściem?
sodium_library_version_major()
to funkcja informująca nas o wersji interfejsu API biblioteki. Nie jest to bezpośrednio związane ze zmianami obsługiwanych/domyślnych algorytmów, więc jest mało przydatne dla naszych problemów.
crypto_sign_primitive()
to funkcja, która zwraca ciąg znaków identyfikujący algorytm używany w crypto_sign()
. To idealnie pasuje do tego, czego potrzebujemy, ponieważ podobno jego wynik zmieni się dokładnie w momencie, w którym algorytm się zmieni.
crypto_sign_bytes()
to funkcja zwracająca rozmiar sygnatury wygenerowanej przez crypto_sign()
w bajtach. Jest to przydatne do określenia ilości pamięci potrzebnej do podpisu, ale może łatwo pozostać niezmieniona, jeśli algorytm się zmieni, więc nie jest to metadane, które musimy zapisać jawnie.
Teraz, gdy wiemy, co przechowywać, istnieje kwestia przetwarzania przechowywanych danych. Musisz uzyskać nazwę algorytmu i użyć go, aby wywołać funkcję weryfikacji dopasowania. Niestety, z tego, co widzę, samo libsodium nie zapewnia żadnego prostego sposobu na uzyskanie prawidłowej funkcji, zważywszy na nazwę algorytmu (np. EVP_get_cipherbyname()
lub EVP_get_digestbyname()
w openssl), więc musisz je wykonać samodzielnie (co oczywiście powinno zawieść dla nieznanego nazwiska). A jeśli musisz samemu zrobić, to może być jeszcze łatwiej przechowywać jakiś numeryczny identyfikator zamiast nazwy z biblioteki (ale więcej kodu).
Przejdźmy teraz do poziomu pliku na poziomie rekordu. Aby rozwiązać ten problem, należy zadać jeszcze dwa pytania: czy można wygenerować nowe podpisy dla starych rekordów w danym momencie (czy jest to technicznie możliwe, czy jest to dozwolone przez zasady) i czy trzeba dołączać nowe rekordy do starych plików?
Jeśli nie można wygenerować nowe sygnatury dla starych płyt lub musisz dołączać nowe rekordy i nie chce kary wydajności regeneracji podpisu, to nie mają wielkiego wyboru i trzeba:
- mieć dynamiczne pole-size dla podpisu
- przechowywać algorytm (dynamiczne pole ciąg lub wewnętrzne (dla aplikacji) ID) służy do generowania podpisu wraz z podpisem samego
Jeśli można wygenerować nowe podpisy lub especi sojusznika, jeśli nie musisz dodawać nowych rekordów, możesz odejść z prostszym podejściem na poziomie pliku, gdy zapisujesz algorytm używany w specjalnym polu na poziomie pliku, a jeśli algorytm podpisu się zmieni, zregeneruj wszystkie podpisy podczas zapisywania plik (lub użyj starego przy dodawaniu nowych rekordów, to także pytanie dotyczące zgodności).
Inne opcje? Cóż, co jest takiego specjalnego w crypto_sign()
? To, że jego zachowanie nie jest pod twoją kontrolą, programiści libsodium wybierają dla ciebie algorytm (bez wątpienia wybierają dobro), ale jeśli masz jakieś informacje o wersjach w twojej strukturze plików (nie chodzi o sygnatury), nic nie przeszkadza ci dokonanie własnego wyboru i użycie jednego algorytmu z jedną wersją pliku, a drugą z inną (oczywiście z kodem konwersji). Ponownie, jest to również oparte na założeniu, że można można wygenerować nowy podpis i jest to dozwolone przez zasady.
Co prowadzi nas z powrotem do pierwotnych dwóch wyborów z pytaniem, czy warto robić to wszystko w porównaniu do używania tylko crypto_sign_ed25519()
. To zależy głównie od długości życia programu, prawdopodobnie powiedziałbym (tak jak opinia), że jeśli to mniej niż 5 lat, łatwiej jest po prostu użyć jednego konkretnego algorytmu. Jeśli może to być z łatwością więcej niż 10 lat, to nie, naprawdę musisz być w stanie przetrwać zmiany algorytmu (i prawdopodobnie nawet całej biblioteki crypto).
Inaczej. Za każdym razem, gdy aktualizujesz swoją bibliotekę, upewnij się, że jest kompatybilna lub zaktualizuj szyfrowanie danych (tak, odszyfruj starym, zaszyfruj z nowym). Opcja polega na trzymaniu starej wersji. Nie sądzę jednak, że libsodium dev's sprawi, że algorytm będzie niekompatybilny, ale nie będzie to możliwe. – user430051
Nie jestem pewien, czy podążam. Kiedy mówisz "zaktualizuj szyfrowanie danych", masz na myśli ponowne podpisanie starych rekordów za pomocą nowego algorytmu? Obawiam się, że to nie zadziała, ponieważ ja (jako programista) nie mam dostępu do prywatnych kluczy użytkowników. Ci użytkownicy i ich klucze mogą nawet dawno zniknąć, jeśli (jeśli) libsodium zmieni algorytm w przyszłości. –