Od dłuższego czasu interesujemy się tematem anonimowości w kryptowalutach i staramy się śledzić rozwój technologii w tej dziedzinie. W naszych artykułach szczegółowo omawialiśmy zasady działania w Monero, a także przeprowadziliśmy technologii istniejących w tym obszarze. Jednak wszystkie anonimowe kryptowaluty, które istnieją obecnie, opierają się na modelu danych zaproponowanym przez Bitcoin — Unspent Transaction Output (UTXO). W przypadku blockchainów opartych na kontach, takich jak Ethereum, istniejące rozwiązania zapewniające anonimowość i poufność (np. lub ) próbowały powtórzyć model UTXO w inteligentnych kontraktach.
W lutym 2019 roku grupa badaczy z Uniwersytetu Stanforda i Visa Research wydali Zether: W stronę prywatności w świecie inteligentnych kontraktów. Autorzy po raz pierwszy zaproponowali podejście do zapewnienia anonimowości w blockchainach opartych na kontach i przedstawili dwa warianty inteligentnego kontraktu: dla transakcji poufnych (ukrywanie sald i kwot przelewów) oraz anonimowych (ukrywanie odbiorcy i nadawcy). Uważamy, że proponowana technologia jest interesująca i chcielibyśmy podzielić się jej mechanizmem oraz porozmawiać o tym, dlaczego problem anonimowości w blockchainach opartych na kontach jest uważany za bardzo złożony i czy autorzy zdołali go całkowicie rozwiązać.
O mechanizmie tych modeli danych
W modelu UTXO transakcja składa się z „wejść” i „wyjść”. Bezpośrednim odpowiednikiem „wyjść” są banknoty w twoim portfelu: każde „wyjście” ma jakiś nominał. Kiedy płacisz komuś (tworzysz transakcję), wydajesz jedno lub więcej „wyjść”, które stają się „wejściami” transakcji, a blockchain oznacza je jako wydane. Odbiorca twojej płatności (lub ty sam, jeśli potrzebujesz reszty) otrzymuje nowo wygenerowane „wyjścia”. Można to schematycznie przedstawić w ten sposób:

Blockchainy oparte na kontach są zorganizowane podobnie do twojego konta bankowego. Operują tylko kwotą na twoim koncie oraz kwotą przelewu. Kiedy przelażysz jakąś kwotę ze swojego konta, nie spalasz żadnych „wyjść”; sieć nie musi pamiętać, które monety zostały wydane, a które nie. W najprostszej formie weryfikacja transakcji sprowadza się do sprawdzenia podpisu nadawcy i kwoty na jego saldzie:

Analiza technologii
W dalszej części omówimy, jak Zether ukrywa kwoty transakcji, odbiorcę i nadawcę. W trakcie opisu zasad jego działania będziemy wskazywać różnice między wersją poufną a anonimową. Ponieważ zapewnienie poufności w blockchainach opartych na kontach jest znacznie prostsze, niektóre ograniczenia związane z anonimizacją będą nieaktualne dla poufnej wersji technologii.
Ukrywanie sald i kwot transferów
Do szyfrowania sald i kwot transferów w Zether stosowany jest schemat szyfrowania . Działa to w następujący sposób. Kiedy Alicja chce wysłać Bobowi b monety na adres (jego klucz publiczny) Y, wybiera losową liczbę r i szyfruje kwotę:

gdzie C — zaszyfrowana kwota, D — wartość pomocnicza, niezbędna do odszyfrowania tej kwoty, G — stały punkt na krzywej eliptycznej, przy mnożeniu klucza prywatnego, z którego uzyskuje się klucz publiczny.
Kiedy Bob otrzymuje te wartości, po prostu dodaje je do swojego zaszyfrowanego w ten sam sposób salda, co czyni ten schemat wygodnym.
W ten sam sposób Alicja odejmuje takie same wartości ze swojego salda, używając jako Y swojego klucza publicznego.
Ukrywanie odbiorcy i nadawcy
Mieszanie 'wyjść' w UTXO pojawiło się już na początku kryptowalut i pomaga ukryć nadawcę. W tym celu sam nadawca, dokonując transferu, wybiera losowe 'wyjścia' z blockchaina i miesza je ze swoimi. Następnie podpisuje 'wyjścia' podpisem pierścieniowym — mechanizmem kryptograficznym, który pozwala przekonać weryfikatora, że wśród wymieszanych 'wyjść' znajdują się monety nadawcy. Same wymieszane monety, oczywiście, nie są wydawane.
Jednakże w celu ukrycia odbiorcy nie będziemy mogli generować fałszywych 'wyjść'. Dlatego w UTXO każde 'wyjście' ma swój unikalny adres, który jest kryptograficznie powiązany z adresem odbiorcy tych monet. Na chwilę obecną nie ma sposobu na ustalenie związku między unikalnym adresem 'wyjścia' a adresem odbiorcy, nie znając jego kluczy prywatnych.
W modelu opartym na kontach nie możemy używać jednorazowych adresów (w przeciwnym razie byłaby to już model „wyjść”). Dlatego nadawca i odbiorca muszą być pomieszani wśród innych kont w blockchainie. Przy tym z pomieszanych kont odejmowane jest 0 monet (lub dodawane 0 — w przypadku pomieszania odbiorcy), co faktycznie nie zmienia ich rzeczywistego salda.
Ponieważ zarówno nadawca, jak i odbiorca zawsze mają stały adres, pojawia się potrzeba używania tych samych grup do pomieszania przy przelewach na te same adresy. Łatwiej to zobrazować na przykładzie.
Załóżmy, że Ala postanowiła dokonać wpłaty na rzecz fundacji charytatywnej Boba, ale woli, aby ten przelew pozostał anonimowy dla zewnętrznego obserwatora. Wówczas, aby zamaskować siebie w polu nadawcy, wpisuje dodatkowe konta Adama i Adeli. A aby ukryć Boba — w polu odbiorcy dodatkowo konta Bena i Billa. Przy następnej wpłacie Ala postanawia wpisać obok siebie Aleksa i Amandę, a obok Boba — Bryana i Benjamina. W takim przypadku podczas analizy blockchaina w tych dwóch transakcjach znajdzie się tylko jedna wspólna para uczestników — Ala i Bob, co deanonimizuje te transakcje.

Wyścigi transakcji
Jak już wspomnieliśmy, aby ukryć swoje saldo w systemach opartych na kontach, użytkownik szyfruje swoje saldo i kwotę przelewu. Przy tym musi dowieść, że saldo na jego koncie pozostaje nieujemne. Problem polega na tym, że tworząc transakcję, użytkownik buduje dowód dotyczący swojego aktualnego stanu konta. A co się stanie, jeśli Bob wyśle do Ali transakcję, która zostanie zaakceptowana przed transakcją wysłaną przez Alę? Wtedy transakcja Ali zostanie uznana za nieważną, ponieważ dowód salda został skonstruowany przed zaakceptowaniem transakcji Boba.

Pierwszym rozwiązaniem, które przychodzi na myśl w takiej sytuacji, jest zamrożenie konta do czasu przeprowadzenia transakcji. Jednak podejście to nie jest adekwatne, ponieważ oprócz trudności w realizacji takiego zadania w zdecentralizowanym systemie, w anonimowym schemacie nie będzie jasne, którego konta zablokować.
Aby rozwiązać ten problem, technologia dzieli transakcje przychodzące i wychodzące: wydawanie środków ma natychmiastowy wpływ na stan salda, podczas gdy przychody są odłożone. Wprowadza się pojęcie „epoki” – grupy bloków o stałej wielkości. Bieżąca „epoka” jest określana przez podział wysokości bloku przez rozmiar grupy. Przetwarzając transakcję, sieć natychmiast aktualizuje saldo nadawcy, a środki odbiorcy są dodawane do akumulatora. Zgromadzone środki stają się dostępne dla odbiorcy płatności dopiero po nadejściu nowej „epoki”.
W efekcie użytkownik może wysyłać transakcje niezależnie od tego, jak często otrzymuje środki (oczywiście w granicach posiadanego salda). Rozmiar epoki określa się na podstawie tego, jak szybko bloki rozprzestrzeniają się w sieci i jak szybko transakcja trafia do bloku.
To rozwiązanie dobrze działa w przypadku poufnych przelewów, jednak w przypadku anonimowych transakcji, jak zobaczymy dalej, stwarza poważne problemy.
Ochrona przed atakami replay
W blockchainach opartych na kontach każda transakcja jest podpisana kluczem prywatnym nadawcy, co przekonuje weryfikującego, że transakcja nie została zmieniona i została utworzona przez właściciela tego klucza. Ale co, jeśli napastnik, który podsłuchuje kanał transmisji, przechwyci tę wiadomość i wyśle dokładnie tę samą drugi raz? Weryfikujący porówna podpis transakcji i będzie przekonany o jej autentyczności, a sieć ponownie odpisze taką samą kwotę z salda nadawcy.
Atak ten nazywa się atakiem replay. W modelu UTXO takie ataki nie są aktualne, ponieważ napastnik będzie starał się wykorzystać wydane transformacje, co samo w sobie jest nieważne i jest odrzucane przez sieć.
Aby zapobiec takiej sytuacji, do transakcji wbudowuje się pole z losowymi danymi, które nazywa się nonce lub po prostu „solą”. Przy ponownym wysyłaniu transakcji z „solą” weryfikujący sprawdza, czy ten nonce był wcześniej używany i jeśli nie, uznaje tę transakcję za ważną. Aby nie przechowywać w blockchainie całej historii nonce'ów użytkowników, zwykle w pierwszej transakcji jego wartość przyjmuje się za równą zeru, a następnie zwiększa o jeden. Sieć musi tylko sprawdzić, że nonce nowej transakcji różni się od poprzedniego o jeden.
W anonimowym schemacie transferów pojawia się problem walidacji nonce'ów transakcji. Nie możemy w sposób jawny powiązać nonce z adresem nadawcy, ponieważ oczywiście dezanonimizuje to transfer. Nie możemy również zwiększać nonce'ów wszystkich uczestniczących kont, gdyż może to kolidować z innymi transferami w trakcie przetwarzania.
Autorzy Zether proponują generować nonce kryptograficznie — w zależności od 'epoki'. Na przykład:

Tutaj x — sekretnego klucza nadawcy, a Gepoch — dodatkowego generatora dla epoki, uzyskiwanego przez haszowanie ciągu w postaci 'Zether + '. Teraz problem, wydawałoby się, zostaje rozwiązany — nie ujawniamy nonce nadawcy i nie ingerujemy w nonce'y osób niezaangażowanych. Jednak takie podejście narzuca poważne ograniczenie: jedno konto może wysłać nie więcej niż jedną transakcję w 'epoce'. Ten problem, niestety, pozostaje nierozwiązany i w obecnej chwili czyni anonimową wersję Zether, naszym zdaniem, mało użyteczną.
Skomplikowanie dowodów z zerowym ujawnieniem
W UTXO nadawca musi udowodnić sieci, że nie wydaje negatywnej sumy, w przeciwnym razie możliwa staje się generacja nowych monet z powietrza (dlaczego to możliwe, pisaliśmy w jednym z wcześniejszych ). A także podpisać 'wejścia' podpisem pierścieniowym, aby udowodnić, że wśród mieszanych monet znajdują się środki, które do niego należą.
W anonimowej wersji blockchaina opartego na kontach, wyrażenia do dowodu stają się znacznie bardziej skomplikowane. Nadawca udowadnia, że:
- Wysłana suma jest dodatnia;
- Bilans pozostaje nieujemny;
- Nadawca poprawnie zaszyfrował kwoty transferów (w tym zerowe);
- Pozostałość na bilansie zmienia się tylko u nadawcy i odbiorcy;
- Nadawca posiada sekret key swojego konta i rzeczywiście znajduje się na liście nadawców (wśród mieszanych);
- Nonce, używany w transakcji, został skonstruowany poprawnie.
Do tak skomplikowanego dowodu autorzy wykorzystują mieszankę (jeden z autorów, nawiasem mówiąc, brał udział w jej stworzeniu) oraz , które nazywają Sigma-bullets. Formalny dowód takiego stwierdzenia — to dość skomplikowane zadanie i mocno ogranicza liczbę chętnych do zajęcia się implementacją technologii.
Co z tego wynika?
Naszym zdaniem, część Zether, która wprowadza prywatność do blockchainów opartych na kontach, może być już wykorzystywana. Jednak obecnie anonimowa wersja technologii wiąże się z poważnymi ograniczeniami w jej użytkowaniu, a jej złożoność wpływa na realizację. Niemniej jednak nie można zapominać, że twórcy wprowadzili ją zaledwie kilka miesięcy temu i być może ktoś inny znajdzie rozwiązanie dla istniejących dziś problemów. W końcu w ten sposób rozwija się nauka.
Źródło: habr.com
