Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce

Kontynuujemy nasz cykl o architekturze blockchaina Monero, a dzisiejszy artykuł poświęcony będzie protokołowi RingCT (Ring Confidential Transactions), który wprowadza transakcje prywatne oraz nowe podpisy ringowe. Niestety, w internecie jest mało informacji na temat jego działania, a my postanowiliśmy zaspokoić tę lukę.

Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce

Omówimy, w jaki sposób ten protokół ukrywa kwoty transferów w sieci, dlaczego zrezygnowano z klasycznych podpisów ringowych typowych dla cryptonote i jak ta technologia będzie się rozwijać w przyszłości.

Ponieważ ten protokół jest jedną z najbardziej skomplikowanych technologii w Monero, czytelnik będzie potrzebował podstawowej wiedzy na temat działania tego blockchaina oraz podstawowej znajomości kryptografii na krzywych eliptycznych (żeby odświeżyć te informacje, można przeczytać pierwsze rozdziały naszego poprzedniego artykułu o podpisach wieloosobowych).

Protokół RingCT

Jednym z możliwych ataków na waluty cryptonote jest analiza blockchaina oparta na znajomości kwoty i czasu wysłania transakcji. Pozwala to znacznie zawęzić obszar poszukiwań interesujących hakerów wyjść. Aby chronić się przed taką analizą, w Monero wprowadzono protokół anonimowych transakcji, który całkowicie ukrywa kwoty transferów w sieci.

Warto zauważyć, że pomysł ukrywania kwot nie jest nowy. Jednym z pierwszych, który opisał to rozwiązanie, był programista Bitcoin Core Greg Maxwell w swoim artykułach o Transakcjach Poufnych. Obecna realizacja RingCT jest modyfikacją tej koncepcji, umożliwiającą stosowanie podpisów ringowych (jakżeby bez nich), i tak właśnie otrzymała swoją nazwę — Ring Confidential Transactions.

Protokół pomaga również wyeliminować problemy związane z mieszaniem niewielkich wyjść — wyjść o małej kwocie (zwykle powstających jako reszta z transakcji), które generowały więcej problemów, niż same kosztowały.

W styczniu 2017 roku miało miejsce hard fork sieci Monero, który umożliwił opcjonalne korzystanie z transakcji poufnych. A już we wrześniu tego samego roku z hard forka wersji 6 takie transakcje stały się jedynymi dozwolonymi w sieci.

RingCT wykorzystuje kilka mechanizmów: wielowarstwowe powiązane spontaniczne anonimowe podpisy grupowe (Multilayered Linkable Spontaneous Anonymous Group Signature, w skrócie MLSAG), schemat zobowiązań (Pedersen Commitments) oraz dowody zakresu (w polskim języku nie ma ustalonego tłumaczenia tego terminu).

Protokół RingCT wprowadza dwa typy anonimowych transakcji: simple i full. Pierwszy jest generowany przez portfel, gdy transakcja wykorzystuje więcej niż jeden wejście, a drugi – w odwrotnej sytuacji. Różnią się one walidacją sum transakcji oraz danymi podpisywanymi podpisem MLSAG (więcej na ten temat poniżej). Co więcej, transakcje typu full można generować z dowolną liczbą wejść, zasadniczo nie ma tutaj różnicy. W książce „Zero to Monero” na ten temat mówi się, że decyzja o ograniczeniu transakcji full do jednego wejścia została podjęta w pośpiechu i w przyszłości może ulec zmianie.

Podpis MLSAG

Przypomnijmy, jakie są podpisywane wejścia transakcji. Każda transakcja wydaje jakieś środki i generuje. Generacja środków odbywa się poprzez tworzenie wyjść transakcji (bezpośredni odpowiednik – banknoty), a wyjście, które transakcja wydaje (bo w rzeczywistości wydajemy tylko banknoty), staje się wejściem (ostrożnie, tutaj łatwo się zgubić).

Wejście odnosi się do kilku wyjść, ale wydaje tylko jedno, tworząc w ten sposób „dymną zasłonę”, aby utrudnić analizę historii przelewów. Jeśli transakcja ma więcej niż jedno wejście, taką strukturę można przedstawić w postaci macierzy, gdzie wiersze to wejścia, a kolumny to mieszane wyjścia. Aby udowodnić sieci, że transakcja wydaje właśnie swoje wyjścia (zna ich tajne klucze), wejścia podpisują się podpisem pierścieniowym. Taki podpis daje gwarancję, że podpisujący znał tajne klucze wszystkich elementów w jakiejkolwiek kolumnie.

Transakcje prywatne nie używają już klasycznych cryptonote podpisów pierścieniowych, ich miejsce zajęły MLSAG – wersja dostosowana do wielu wejść analogicznych do jednowarstwowych podpisów pierścieniowych, LSAG.

Nazywają się wielowarstwowymi, ponieważ podpisują jednocześnie kilka wejść, z których każde jest mieszane z kilkoma innymi, tzn. podpisywana jest macierz, a nie jeden wiersz. Jak zobaczymy później, pomaga to zaoszczędzić na rozmiarze podpisu.

Przyjrzyjmy się, jak formułowany jest podpis pierścieniowy, na przykładzie transakcji, która wydaje 2 rzeczywiste wyjścia i wykorzystuje do mieszania m – 1 losowe z blockchaina. Oznaczmy klucze publiczne wyjść, które wydajemy, jako
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce, a obrazy kluczy dla nich odpowiednio: Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce W ten sposób otrzymujemy macierz o wymiarach 2 x m. Najpierw musimy obliczyć tzw. wyzwania dla każdej pary wyjść:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Obliczenia zaczynamy od wyjść, które wydajemy, używając ich kluczy publicznych:Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejscei liczb losowychTransakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsceW rezultacie otrzymujemy wartości:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce, które wykorzystujemy do obliczenia wyzwania
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejscenastępnej pary wyjść (aby łatwiej zrozumieć, co i gdzie podstawiamy, wyróżniliśmy te wartości różnymi kolorami). Wszystkie następne wartości są obliczane cyklicznie według wzorów podanych na pierwszej ilustracji. Ostatnim obliczanym wyzwaniem jest to dla pary rzeczywistych wyjść.

Jak widać, we wszystkich kolumnach poza tą zawierającą rzeczywiste wyjścia używane są losowo wygenerowane liczbyTransakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce. Dla π-tej kolumny również będą nam potrzebne. PrzekształcamyTransakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejscew s:Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Podpis sam w sobie jest krotką wszystkich tych wartości:

Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce

Następnie te dane są zapisywane w transakcji.

Jak widać, MLSAG zawiera tylko jedno wyzwanie c0, co pozwala zaoszczędzić miejsce na podpisie (które i tak zajmuje dużo miejsca). Następnie każdy weryfikator, używając danychTransakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce, przywraca wartości c1,…, cm i sprawdza, żeTransakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce. W ten sposób nasze koło się zamknęło, a podpis przeszedł weryfikację.

Dla transakcji RingCT typu full dodawany jest jeszcze jeden wiersz do macierzy z wymieszanymi wyjściami, ale o tym opowiemy później.

Pedersen Commitments

Schematy zobowiązań (częściej używa się anglojęzycznego terminu — commitments) są używane do tego, aby jedna strona mogła udowodnić, że zna pewien sekret (liczbę), faktycznie go nie ujawniając. Na przykład, rzucasz kostką pewną liczbę, obliczasz zobowiązanie i przekazujesz je stronie weryfikującej. W ten sposób, w momencie ujawnienia sekretniej liczby, weryfikator samodzielnie oblicza zobowiązanie, upewniając się, że go nie oszukiwałeś.

W Monero zobowiązania są używane do ukrywania kwot przelewów i stosują najpopularniejszy wariant — Pedersen commitments. A przy okazji ciekawostka — początkowo deweloperzy proponowali ukrywać kwoty zwykłym zamieszaniem, to znaczy dodawając wyjścia o losowych kwotach, aby wprowadzić niepewność, ale później przeszli na zobowiązania (przy czym nie jest pewne, że zaoszczędzili na wielkości transakcji, jak zobaczymy poniżej).
W ogólnym przypadku zobowiązanie wygląda następująco:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsceGdzie C — wartość samego zobowiązania, a — ukrywana suma, H — stała punkt na eliptycznej krzywej (dodatkowy generator), a x — pewna losowa maska, ukrywający czynnik, generowany losowo. Maska jest potrzebna, aby strona trzecia nie mogła w prosty sposób dobrać wartości commitment.

Podczas generowania nowego wyjścia portfel oblicza dla niego commitment, a przy wydatkowaniu bierze albo wartość obliczoną podczas generacji, albo przelicza ją na nowo — w zależności od rodzaju transakcji.

RingCT simple

W przypadku transakcji simple RingCT, aby zagwarantować, że transakcja stworzyła wyjścia o równowartości sumy wejść (nie wytworzyła pieniędzy z powietrza), suma commitments pierwszych i drugich musi być taka sama, to znaczy:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Commitment opłat oblicza się trochę inaczej — bez maski:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce, gdzie a — suma opłaty, jest publicznie dostępna.

Takie podejście pozwala udowodnić stronie kontrolującej, że używamy tych samych kwot, nie ujawniając ich.

Aby wszystko stało się jaśniejsze, rozważmy przykład. Załóżmy, że transakcja wydaje dwa wyjścia (czyli stają się one wejściami) na 10 i 5 XMR i generuje trzy wyjścia na sumę 12 XMR: 3, 4 i 5 XMR. Przy tym płaci opłatę 3 XMR. W ten sposób suma wydanych pieniędzy plus suma wygenerowanych i opłata wynosi 15 XMR. Spróbujmy obliczyć commitments i zobaczyć różnicę ich sum (przypomnijmy sobie matematykę):

Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Tutaj widzimy, że aby równanie się zgadzało — sumy masek wejść i wyjść muszą być takie same. W tym celu portfel generuje losowo x1, y1, y2 i y3, a pozostałe x2 oblicza tak:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Używając tych masek, możemy udowodnić każdemu kontrolującemu, że nie generujemy środków więcej, niż wydajemy, nie ujawniając sum. Oryginalnie, prawda?

RingCT full

W full RingCT transakcjach kontrola sum przelewów przebiega nieco bardziej skomplikowanie. W tych transakcjach portfel nie przelicza commitments dla wejść, ale używa tych obliczonych podczas ich generacji. Należy przyjąć, że różnica sum nie będzie już równa zeru, a zamiast tego:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Tutaj z — różnica masek wejść i wyjść. Jeśli rozważyć zG jako klucz publiczny (czym de facto jest), to z — to jest klucz prywatny. W ten sposób znamy klucz publiczny oraz odpowiadający mu klucz prywatny. Mając te dane, możemy je wykorzystać w podpisie ringowym MLSAG razem z publicznymi kluczami mieszanych wyjść:
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
W ten sposób ważny podpis ringowy gwarantuje, że znamy wszystkie klucze prywatne jednego z kolumn, a klucz prywatny w ostatnim wierszu możemy znać tylko wtedy, gdy transakcja nie generuje środków więcej, niż wydaje. Przy okazji, tutaj odpowiedź na pytanie „dlaczego różnica sum zobowiązań nie prowadzi do zera” — jeśli zG = 0, to ujawniamy kolumnę z rzeczywistymi wyjściami.

A jak odbiorca środków dowie się, ile pieniędzy mu przesłano? Tutaj wszystko jest proste — nadawca transakcji i odbiorca wymieniają się kluczami za pomocą protokołu Diffiego-Hellmana, używając klucza transakcji i klucza view odbiorcy oraz wyliczają wspólny sekret. Nadawca zapisuje w specjalnych polach transakcji dane o kwotach wyjść, zaszyfrowane tym wspólnym kluczem.

Dowody zakresu

A co się stanie, jeśli jako sumę w zobowiązaniach użyjemy liczby ujemnej? To może prowadzić do generacji dodatkowych monet! Taki wynik jest niedopuszczalny, dlatego potrzebna jest gwarancja, że używane przez nas kwoty są nieujemne (bez ujawnienia tych kwot, rzecz jasna, w przeciwnym razie tyle trudu i wszystko na nic). Innymi słowy, musimy udowodnić, że suma znajduje się w zakresie [0, 2n — 1].

W tym celu suma każdego wyjścia dzieli się na bity i liczy się zobowiązanie dla każdego bitu osobno. Jak to wygląda, najlepiej omówić na przykładzie.

Załóżmy, że kwoty są niewielkie i mieszczą się w 4 bitach (w praktyce to 64 bity), a my tworzymy wyjście na kwotę 5 XMR. Liczymy zobowiązania dla każdego bitu i ogólne zobowiązanie na całą kwotę:Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsce
Następnie każde zobowiązanie jest mieszane z surrogatem (Ci-2iH) i podpisywane parami podpisem ringowym Borromeo (jeszcze jednym podpisem ringowym), zaproponowanym przez Grega Maxwella w 2015 roku (więcej o nim można przeczytać tutaj):
Transakcje prywatne w Monero, czyli jak przesłać coś nieznanego w nieznane miejsceWszystko razem nazywa się dowodem zakresu i pozwala zapewnić, że w zobowiązaniach używane są kwoty w ramach [0, 2n — 1].

Co dalej?

W bieżącej implementacji dowody zakresu zajmują bardzo dużo miejsca — 6176 bajtów na jedno wyjście. Prowadzi to do dużych transakcji i, w konsekwencji, wyższych opłat. Aby zmniejszyć rozmiar transakcji Monero, deweloperzy wprowadzają zamiast podpisów Borromeo bulletproofs — mechanizm dowodu zakresu bez commitmentów bitowych. Według niektórych szacunków, są w stanie zmniejszyć rozmiar dowodu zakresu o 94%. Przy okazji, w połowie lipca technologia przeszła audyt przeprowadzony przez firmę Kudelski Security, która nie wykazała istotnych wad ani w samej technologii, ani w jej realizacji. Technologia jest już stosowana w sieci testowej, a po nowym hard forku może trafić także do sieci głównej.

Zadawaj pytania, proponuj tematy do nowych artykułów o technologiach w obszarze kryptowalut, a także subskrybuj naszą grupę w Facebook, aby być na bieżąco z naszymi wydarzeniami i publikacjami.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster