Myślisz, że wdrożenie nonce'ów jest proste? Pomyśl jeszcze raz. Niezależnie od tego, czy budujesz protokoły on-chain, czy infrastrukturę off-chain, prawidłowe wdrożenie nonce'ów jest jednym z najtrudniejszych elementów bezpieczeństwa kryptograficznego. Zanurzmy się w to, dlaczego ochrona przed powtórkami jest trudniejsza, niż się wydaje 👇
2/ Najpierw zrozummy podpisy cyfrowe. W kryptografii z kluczem publicznym (takiej jak BLS) masz klucz prywatny, który podpisuje wiadomości, oraz klucz publiczny, który je weryfikuje. W Ethereum: adres = skrót klucza publicznego wiadomość = skrót transakcji podpis = 64 bajty dowodu kryptograficznego
3/ Oto problem: matematyka w większości protokołów kryptograficznych z kluczem publicznym nie ogranicza, ile razy podpis może być weryfikowany w stosunku do tej samej wiadomości. Gdy masz ważny podpis, możesz go odtwarzać w nieskończoność. To otwiera drzwi do ataków powtórkowych.
4/ Wprowadź nonce: "liczba używana raz", która zapobiega atakom powtórzeniowym. Gdy konsument otrzymuje wiadomość z nonce, sprawdza, czy ten nonce był używany wcześniej. Jeśli tak → odrzuć. Transakcje Ethereum korzystają z tego wzorca.
5/ Jednak implementacja nonce jest zwodniczo skomplikowana. Kluczowe wymagania: - Nonce NIGDY nie mogą być ponownie używane (na tym łańcuchu ani innych) - Muszą na stałe zapobiegać atakom powtórzeniowym - Potrzebne są mechanizmy do obsługi wzrostu pamięci - Muszą być odporne na ataki front-running
6/ Naiwne rozwiązanie: przechowywać wszystkie nonces w bazie danych na zawsze. To ma dwa główne problemy: a) Nieograniczony wzrost pamięci (szczególnie w przypadku ataków spamowych) b) Wrażliwość na ataki front-runningowe Problem (a) jest łatwiejszy do rozwiązania niż (b). Zajmijmy się najpierw pamięcią...
7/ Nonce'y oparte na znaczniku czasu rozwiązują problem wzrostu pamięci! Użyj znacznika czasu + okresu ważności. Nonce starsze niż 5 minut są usuwane z bazy danych. Ale co z równoczesnymi wiadomościami z tego samego konta? Dzielą się znacznikiem czasu. Rozwiązanie: znacznik czasu + random_bytes dla granularnej unikalności.
8/ Front-running to trudna sprawa. Złośliwi aktorzy mogą przechwytywać ważne podpisy, a następnie je wyprzedzać, aby oznaczyć nonces jako użyte, co skutkuje odrzuceniem wywołania przez prawdziwego użytkownika. To jest problematyczne na łańcuchu z operacjami zbiorczymi, jeśli jeden zły podpis odrzuca całą partię. W przypadku offchain: używaj szyfrowania TLS! Nie pozwól, aby jakikolwiek złośliwy aktor kiedykolwiek zobaczył nonce lub podpis.
9/ Nie zapominaj o wytrwałości! Jeśli twoja pamięć podręczna nonce jest tylko w pamięci, napastnicy mogą odtwarzać stare nonces po ponownym uruchomieniu systemu. Zawsze zapisuj stan nonce w trwałej pamięci i ładuj przy starcie. Pamięciowe pamięci podręczne = okno podatności na odtwarzanie.
10/ Unikalne nonce dla każdego konsumenta! Podczas nadawania do wielu użytkowników, każdy powinien otrzymać inną wiadomość/podpis. W przeciwnym razie jesteś narażony na ataki typu Man-in-the-Middle, gdzie jeden odbiorca przekazuje wiadomość, podszywając się pod oryginalnego nadawcę.
11/ Inkrementalne nonces (jak w Ethereum, nonce = poprzedni nonce + 1) mają swoje miejsce, ale uważaj! Tworzą ogromne wyzwania dla infrastruktury offchain: wiadomości w nieodpowiedniej kolejności, problemy z synchronizacją i skomplikowane scenariusze odzyskiwania. Używaj tylko, jeśli jesteś pewien, że wiadomości będą (lub muszą) przychodzić w kolejności.
Podsumowanie - Lista kontrolna implementacji nonce: ✅ Używaj nonce'ów, aby zapobiegać atakom powtórkowym ✅ Utrzymuj stan nonce'a po ponownych uruchomieniach ✅ Wprowadź mechanizmy wygasania (znacznik czasu + czyszczenie) ✅ Uczyń nonce'y unikalnymi dla każdego odbiorcy ✅ Chroń przed front-runningiem za pomocą szyfrowanych kanałów ✅ Unikaj inkrementalnych nonce'ów, chyba że kolejność jest gwarantowana Bezpieczeństwo tkwi w szczegółach! 🛡️
1,44K