Hej, miło mi, że ktoś to czyta :)
System został zaprojektowany od podstaw z myślą o bezpieczeństwie. Pierwsze zabezpieczenia wchodzą w grę już na etapie logowania. Użytkownik, logując się, nie przesyła swojego hasła na serwer. Zamiast tego strona wykorzystuje protokół OCAKE . Jak to działa? Serwer generuje jednorazowe "wyzwanie" dla klienta, a klient na podstawie hasła tworzy odpowiedź. Po weryfikacji odpowiedzi serwer wie, że użytkownik zna hasło, ale nigdy go nie widział. Dzięki temu nawet w przypadku podsłuchu komunikacji lub przejęcia serwera, hasło pozostaje bezpieczne. Celem zapewnienia PQ-safe wymieniliśmy Dh w protokole SRP na Krystars Kyber. Czy jest to idealne nie, czy jest to robienie własnego crytpo tak, czy mamy jakiś wybór nie za badzo, bo nie ma protokołu quantum safe np. OPQQUE też nie jest Quantum safe a implementacje społeczności są takimi samymi prototypami jak nas. Czy jesteśmy z tego dumni nie, ale nie mamy wyjścia. Omówienie protokołu logowania
rejestracja
1. Użytkownik generuje salt
2. użytkownik na podstawi salta i hasła generuje ziarno
3. na podstawnie p.2 klient geenruje pare kluczy
3. zapisuje sól i klcuz publiczny na serweże
do tego momentu nie ma dużych różnic od SRP poza algorytmem. No musze wymienić ;)
logowanie.
1. server generuje jednorazowy klucz
2. generuje kapsułe bazując na kluczu publicznym klienta
3. server wysyła do klienta jednorazowy klucz, statyczną sul i losowe wyzwanie
4. client generuje z hasła i soli generuje pare kluczy
4. client generuje kapsułe i współdzielony sekret z jednorazowego klucza serwera
5. client generuje dekapsułuje shared secret od serwera
6. client generuje ostateczny secret HASH(sharedsecret1+sharedsecret2)
7. client oblicza odpowiedź HMAC(wyzwanie, ostateczny sektret)
8. client generuje wyzwanie servera
9. client przesyła na server odpowiedź, kapsułe i wyzwanie serwera
10. server dekapułuje kapsułe
12. server ostateczny sekret = HAsh(sharedsecret1+sharedsecret2)
13. serwer weryfikuje odpowiedź clienta
14. server generuje odpowiedź dla klienta HMAC(wyzwanie servera, ostateczny sektret)
15. serwer odsyła klientowi odpowiedź
16. client weryfikuje odpowiedż
To jest bardzo prosty protokół angażująćy 2 funkcje KEM i HASH. Prostota nic nie gwarantuje ale przynajmniej nie robiłem włąsnych "klocków" tylko je skłądam co jest zdecydowanie lepszym pomysłem mimo że wciąż nie idealnym
Protokół Logowania (Diagram)
Aby lepiej zobrazować proces logowania, poniżej przedstawiamy uproszczony diagram przepływu:
Szczegółowy opis kroków znajduje się w tekście powyżej.
Dlaczego to ważne?
Nawet jeśli atakujący przejmie serwer, nie uzyska dostępu do haseł. Kolejnym elementem jest pełna infrastruktura PKI (Public Key Infrastructure). Podczas pierwszego logowania generowane są dwie pary kluczy w standardzie CRYSTALS-Kyber oraz CRYSTALS-Dilithium (algorytmy postkwantowe co jest zgodne z FIPS 204, FIPS 203 oraz zaleceniami NIST co do twożenia nowych systemów dla wyturców systemów dla rządu USA przetważające dane poufne ponieważ dane poufne muszą być tajne przez conajmniej 10 lat). Jest to moja implementacja biblioteki liboqs w JavaScript przy użyciu WebAssembly (WASM). Nie modyfikowałem kodu samej biblioteki, a jedynie importy, więc nie powinno to wpłynąć na bezpieczeństwo.
Klucze są szyfrowane hasłem za pomocą algorytmu Argon2id z parametrami: 500 MB pamięci, 3 iteracje, równoległość 2. Te parametry zostały starannie dobrane, aby zapewnić wysoki poziom bezpieczeństwa przy jednoczesnym zachowaniu akceptowalnego czasu logowania dla użytkownika. 500 MB pamięci utrudnia ataki brute-force wykorzystujące akceleratory sprzętowe (np. GPU) i ASIC, ponieważ wymagają one dużej ilości pamięci RAM. 3 iteracje i równoległość 2 dodatkowo zwiększają koszt obliczeniowy ataku, jednocześnie utrzymując czas szyfrowania na poziomie około 3 sekund. Taki czas opóźnienia skutecznie chroni przed masowymi atakami brute-force, gdzie atakujący próbuje złamać wiele haseł jednocześnie.
Salt jest losowym ciągiem znaków powiązanym z użytkownikiem, co dodatkowo utrudnia ataki słownikowe i tęczowe tablice.
Zabezpieczenia kluczy i sesji
Po odszyfrowaniu klucza jest on zabezpieczany kluczem sesji przechowywanym na serwerze oraz w indexedDB z flagą exportable: false. Sesja jest ważna przez 4 godziny, po czym wygasa. Ciasteczka (cookies) są zabezpieczone flagami Secure, HttpOnly oraz SameSite=Strict. Sesja jest zarządzana przez backend w C#. Gdy sesja wygaśnie, w przeglądarce nie pozostają żadne wrażliwe dane.
Weryfikacja kluczy i zaufanie
Każdy użytkownik ma dostęp do kluczy publicznych innych użytkowników, ale zalecam ręczną weryfikację odcisku klucza poprzez przycisk "Pokaż klucze". W tej funkcji zostanie wyświetlony odcisk palca klucza do podpisów innego użytkownika. Jeśli użytkownik go zweryfikuje, może kliknąć przycisk “zaufaj”, co spowoduje podpisanie przez niego klucza drugiej osoby, co w oczach systemu oznaczy go jako “zaufany”.
Mechanizmy ochrony przed podmianą kluczy
Co jednak, jeśli serwer podmieni klucz użytkownika? Do ochrony przed tym mamy dwa mechanizmy:
- Serwer nie zna hasła, więc nie może zaszyfrować klucza tajnego (używamy AES, czyli szyfru symetrycznego).
- Przy każdym logowaniu wyświetlane jest 8 emotek symbolizujących około 10 pierwszych bajtów odcisku palca klucza publicznego Dilithium. Użytkownik w dowolnym momencie może wyświetlić pełny odcisk palca, ale emotki służą jako szybkie skojarzenie, że wszystko jest w porządku. Jeśli użytkownik zauważy zmianę emotek, będzie wiedział, że jego klucz został podmieniony.
Zaufanie między użytkownikami
Zaufanie między użytkownikami odbywa się poprzez porównanie pełnego odcisku SHA256. Użytkownikom wyświetlany jest odcisk bez ostatnich 5 znaków, a celem weryfikacji jest wprowadzenie tych brakujących znaków. Jeśli się zgadzają, klient podpisuje swoim kluczem tożsamości klucz drugiej strony. Dzięki temu użytkownik wie, że klucz drugiej strony się nie zmienił.
Forward Secrecy (FS)
Co do Forward Secrecy (FS), istnieje możliwość rotacji klucza Kyber w dowolnym momencie. Po rotacji klucz jest podpisany kluczem Dilithium, więc zaufanie nie jest naruszone, ponieważ zaufanie dotyczy kluczy Dilithium. Klucze Kyber są przechowywane na serwerze jako archiwalne, aby umożliwić dostęp do starych wiadomości.
Integracja z HIBP
Dzięki integracji z HIBP (Have I Been Pwned) sprawdzamy, czy hasło nie wyciekło. Wysyłamy jedynie 5 pierwszych znaków hasha hasła, a HIBP zwraca pasujące sufiksy. Dzięki temu ani my, ani HIBP nie znamy pełnego hasła.
Inne zabezpieczenia
- 2FA oparte o TOTP oraz FIDO.
- Protekcja przed CSRF poprzez tokeny w formularzach.
-
Nagłówki bezpieczeństwa: Stosujemy szereg nagłówków HTTP, aby zwiększyć bezpieczeństwo aplikacji po stronie klienta i przeglądarki użytkownika:
X-Frame-Options: DENY - Ochrona przed Clickjackingiem. Ten nagłówek zapobiega osadzaniu strony w ramkach `iframe` na innych stronach, co chroni przed atakami typu clickjacking, gdzie atakujący może próbować nakłonić użytkownika do nieświadomego kliknięcia na ukryte elementy strony.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload - Wymuszanie HTTPS i ochrona przed atakami typu Downgrade. Ten nagłówek informuje przeglądarkę, że strona powinna być zawsze dostępna tylko przez HTTPS. `max-age` określa czas ważności tego wymuszenia (2 lata), `includeSubDomains` rozszerza to na wszystkie poddomeny, a `preload` umożliwia włączenie domeny do listy "preload HSTS" w przeglądarkach, co zapewnia ochronę nawet przy pierwszym połączeniu. Chroni to przed atakami typu man-in-the-middle, które mogłyby próbować "zdegradować" połączenie do niezabezpieczonego HTTP.
X-Content-Type-Options: nosniff - Ochrona przed MIME-sniffingiem. Ten nagłówek instruuje przeglądarkę, aby nie próbowała "zgadywać" typu MIME zasobu na podstawie jego zawartości, ale polegała na typie MIME podanym przez serwer. Chroni to przed atakami, które wykorzystują błędną interpretację typów plików przez przeglądarkę.
Content-Security-Policy: default-src 'self' example.pl:452 strict-dynamic nonce-; - Ograniczenie źródeł zasobów i ochrona przed XSS. CSP to złożony nagłówek, który definiuje politykę bezpieczeństwa treści. `default-src 'self' example.pl:452` ogranicza domyślne źródła zasobów (skryptów, obrazków, stylów itp.) do własnej domeny i konkretnej domeny `example.pl:452`. `strict-dynamic nonce-` w połączeniu z nonce (losowym ciągiem znaków generowanym dynamicznie) wzmacnia ochronę przed atakami Cross-Site Scripting (XSS) poprzez umożliwienie uruchamiania tylko zaufanych skryptów. (Warto tutaj dodać, że 'example.pl:452' to tylko przykład i w rzeczywistości podać prawdziwą domenę/port, jeśli jest używany zewnętrzny zasób)
- Wykorzystanie mosparo do ochrony przed botami.
- Szyfrowane codzienne backupy.
- Serwer z dostępem tylko przez HTTPS (port 443) i SSH z autoryzacją kluczem (port 9022).
- WAF (Web Application Firewall) i monitoring anomalii w OpenSearch.
Struktura Uprawnień
- Wszystkie wiadomości (nie szyfrowane) Odczyt/Modyfikacja
- Wszystkie opinie Odczyt/Modyfikacja
- Wszystkie oznaczone notatki Odczyt
- Wszystkie zajęcia Odczyt/Modyfikacja
- Wszystkie instancje zajęć Odczyt/Modyfikacja
- Wszystkie współdzielone notatki Odczyt
- Wszystkie obecności Odczyt/Modyfikacja
- Użytkownicy Odczyt/Modyfikacja
- Użytkownicy Odczyt/Modyfikacja
- Wszystkie RCP / urlopy Odczyt/Modyfikacja
- Wszystkie RCP / urlopy (swoich podwładnych) Odczyt/Modyfikacja
- Wszystkie opinie Odczyt/Modyfikacja
- Wszystkie zajęcia Odczyt
- Swoje zajęcia Odczyt/Modyfikacja
- Swoje instancje zajęć Odczyt/Modyfikacja
- Swoje RCP/ Uropy (edycja tylko nie zatwierdzonych) Odczyt/Modyfikacja
- swoje i udostępnione notatki Odczyt
- Swoje zajęcia Odczyt + możliwość odwołania
- Swoje instancje zajęć Odczyt
- Swoje wiadomości (rodzic nie widzi daty odczytania) Odczyt
- Wszyscy użytkownicy Odczyt