Ukazał się Ad Nihilum 0.4.3 — minimalistyczna usługa wymiany zaszyfrowanych wiadomości na zasadzie „przeczytane — spalone”, skierowana przede wszystkim na self-hosting.
Serwer pełni jedynie rolę nieczułego magazynu. Szyfrowanie i deszyfrowanie odbywają się wyłącznie po stronie klienta, w przeglądarce (przez AES-GCM).
Cechy
- lokalne szyfrowanie i deszyfrowanie, serwer nigdy nie widzi klucza;
- wsparcie dla dodatkowej warstwy szyfrowania hasłem, o którym (1) serwer nie może wiedzieć, (2) nie można poznać po przekazywanym linku;
- projekt zawiera około 2200 linii kodu serwera w C i 600 linii kodu klienta w JS, co ułatwia audyt;
- Ad Nihilum zależy tylko od libmicrohttpd. Do generowania kodów QR dostarczana jest zmodyfikowana wersja QRCode.js;
- dołączona instrukcja szybkiego uruchomienia lokalnej usługi bez zewnętrznego IP;
- Ad Nihilum działa również na Androidzie, dołączony odpowiedni skrypt do budowy w Termux;
- jedno-wątkowy i synchroniczny serwer.
Zmiany
Ogromny redesign
- Strony wysyłania i odbierania wiadomości zostały oddzielone, odpowiedni kod klienta.
- Ogólnie projekt został mocno zmieniony i dostosowany do sugestii lorce.
- „Prosty” i lokalny klienci:
- Strony klienckie można zapisać lokalnie i używać z file://.
Polityki przeglądarki
- wdrożono CSP w celu walki z XSS;
- serwer wysyła HSTS.
Inne zmiany
- projekt został przemianowany z Epha-ots;
- zakupiono domenę adnihilum.net;
- TLS jest zapewniane przez Let’s Encrypt, warto to mieć na uwadze (nie ma pieniędzy);
- usprawniono pracę z plikami;
- przejście na wskaźniki fat-pointer;
- naprawiono drobne błędy;
- auto-jsminify i budowa plików klienckich przy kompilacji przez CMake.
Przegląd protokołu
Wygenerować trzy losowe wartości: klucz, K, wektor inicjalizacji N i sól S. K — 256 bitów, N — 96 bitów, S — 128 bitów.
Wypłacić ID z K i S z wykorzystaniem HKDF opartego na SHA-256.
Uformować ciąg dodatkowych uwierzytelnionych danych aad — to zwykły ciąg w formie: id=ID
Jeśli użytkownik ustawił hasło:
- wyprowadzić Pk z hasła i S z wykorzystaniem PBKDF2, SHA-256, 800000 iteracji;
- te sama sól używana jest wszędzie;
- zaszyfrować dane za pomocą AES-GCM, używając klucza Pk, IV/nonce N i przekazać aad.
Dodać dwubajtowy znacznik do już zaszyfrowanych danych, jeśli hasło było, lub do danych źródłowych, jeśli hasła nie było.
Pierwszy bajt ma wartość: wskazuje, czy dane były szyfrowane hasłem:
- 0x73 — dane są szyfrowane hasłem;
- 0x13 — dane nie są szyfrowane hasłem.
Drugi bajt — stała wartość 0x37.
Ponownie zaszyfruj wynik za pomocą AES-GCM, używając tego samego iv = N oraz ten sam aad. To daje finalny szyfrogram ct.
Połącz bajty w ciąg: blob = N .. S .. ct
Wyślij blob na serwer razem z ID. Serwer zwraca blob na tej podstawie ID i nie może go podmienić: klient najpierw sprawdzi ID z użyciem N i K jeszcze przed odszyfrowaniem, a następnie — przez aad.
Klient przechowuje K. K nigdy nie jest wysyłane na serwer. Pk też nie jest wysyłane; wszystko, co związane z hasłem, jest usuwane z pamięci.
Klient formuje link: origin/#ID/K
Tutaj ID i K — ciągi w formacie base64url.
Gdy odbiorca otwiera link:
- przeglądarka odrzuca wszystko, co zaczyna się od #; to się nazywa location.hash;
- aplikacja kliencka ładowana jest z serwera;
- moim zdaniem, to jest główną luką: w rzeczywistości znowu wracamy do tego, że 'TLS jest dziurawy';
- nie ma jednak nic, co by przeszkadzało w przechowywaniu klienta offline;
- w idealnym przypadku powinien być osobny klient samodzielny.
Klientski JavaScript sprawdza location.hash, a jeśli jest tam ID i K, pobiera dane z serwera.
Następnie sprawdza je, odszyfrowuje i, w razie potrzeby, prosi o hasło i odszyfrowuje ponownie.
Licencja
Projekt jest rozpowszechniany na licencji GPLv3.
Źródło: linux.org.ru
