Hjem
Artikler
Forbedring af kryptogennemsigtighed med zero-knowledge proofs

Forbedring af kryptogennemsigtighed med zero-knowledge proofs

Let øvet
Offentliggjort Feb 10, 2023Opdateret Jan 5, 2024
10m

TL;DR

Et zero-knowledge proof gør det muligt for en part (verifikatoren) at afgøre gyldigheden af et udsagn fra en anden part (beviseren) uden at kende til udsagnets indhold. F.eks. kan Binance ønske at bevise, at de har sikret deres brugeres midler fuldt ud i reserver uden at afsløre alle individuelle brugeres saldi.

Et "Proof of Reserves" kan konstrueres med et Merkle-træ, der beskytter mod forfalskning af dets interne data, i dette tilfælde dets samlede nettokundesaldoer, som er børsens forpligtelser over for sine brugere. Dette kan så kombineres med en zk-SNARK (en zero-knowledge proof-protokol), der sikrer, at brugerne kan kontrollere, at deres saldo er en del af den samlede nettobalance for brugeraktiver uden at kende de individuelle saldi.

Introduktion

I lyset af begivenhederne på markedet er sikkerheden for kryptoaktiver i forvaltning blevet et kritisk emne. Blockchain-brugere sætter stor pris på gennemsigtighed og åbenhed, men støtter også beskyttelse af personoplysninger og fortrolighed. Det skaber et dilemma, når man skal bevise reserver af midler, der opbevares af forvaltere. Ofte er der en afvejning mellem gennemsigtighed, tillid og datafortrolighed.

Dette behøver dog ikke at være tilfældet. Ved at kombinere zero-knowledge proof-protokoller såsom zk-SNARK'er med Merkle-træer kan vi finde en effektiv løsning for alle parter.

Hvad er zero-knowledge proof?

Et zero-knowledge proof gør det muligt for en part (verifikatoren) at afgøre gyldigheden af et udsagn fra en anden part (beviseren) uden at kende til udsagnets indhold. Lad os se på et enkelt eksempel.

Du har et aflåst pengeskab, som kun du kender koden til. For eksemplets skyld kan pengeskabet ikke dirkes eller tvinges op eller på anden måde åbnes uden at kende kombinationen. Dette faktum er også fastslået, verificeret og kendt af din ven, der deltager i eksperimentet.

Du siger til din ven, at du kender kombinationen, men du vil ikke give den væk eller åbne pengeskabet foran vedkommende. Øverst på pengeskabet er der et hul, som din ven kan føre en seddel igennem. For at gøre dette til et zero-knowledge proof, bør din ven ikke have nogen ekstra oplysninger om processen ud over den givne erklæring.

Du kan bevise over for din ven, at du kender kombinationen, ved at åbne pengeskabet, fortælle, hvad der står på sedlen, og lukke det igen. Du har dog på intet tidspunkt afsløret kombinationen.

For et mere avanceret eksempel kan du læse vores artikel Hvad er zero-knowledge proof, og hvordan påvirker det blockchainen?

Hvorfor bruger vi zero-knowledge proofs?

Zero-knowledge proofs er velegnede til at bevise noget uden at afsløre følsomme oplysninger eller detaljer. Det kan være tilfældet, hvis du ikke ønsker at udlevere dine økonomiske eller personlige oplysninger, som kan blive brugt på en uhensigtsmæssig måde.

I krypto kan du bevise, at du ejer en private key uden at afsløre den eller signere noget digitalt. En kryptovalutabørs kan også ønske at bevise status for sine reserver uden at afsløre fortrolige oplysninger om sine brugere, herunder deres individuelle kontosaldi. 

Til disse eksempler (og mange andre) vil et zero-knowledge proof bruge algoritmer, der tager et datainput og returnerer "sandt" eller "falsk" som output. 

Definition af zero-knowledge proofs i tekniske termer

Et zero-knowledge proof følger teknisk set en bestemt struktur med visse kriterier. Vi har allerede dækket beviser- og verifikatorrollerne, men der er også tre kriterier, som et zero-knowledge proof bør dække:

  1. Fuldstændighed. Hvis udsagnet er sandt, vil en verifikator blive overbevist af det fremlagte bevis uden behov for andre oplysninger eller verifikation.

  2. Soliditet. Hvis udsagnet er falsk, vil en verifikator ikke blive overbevist om et udsagns sandhed af det fremlagte bevis.

  3. Zero-knowledge. Hvis udsagnet er sandt, får verifikatoren ingen andre oplysninger, end at udsagnet er sandt.

Hvad er en zk-SNARK?

En zk-SNARK (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) er en bevisprotokol, der følger principperne for zero-knowledge, der tidligere er angivet. Med en zk-SNARK kan du bevise, at du kender den oprindelige hashede værdi (gennemgået længere nede) uden at afsløre, hvad den er. Du kan også bevise gyldigheden af en transaktion uden at afsløre nogen oplysninger om de specifikke beløb, værdier eller adresser, der er involveret.

zk-SNARK'er er almindeligt brugt og debatteret i blockchain- og kryptovalutaverden. Men du undrer dig måske over, hvorfor nogen gider bruge en zk-SNARK, når de kan bruge en simpel metode til at parre en public og en private key til at sikre oplysningerne. Vi ville dog ikke være i stand til at implementere det matematiske bevis for at sikre, at ingen negative saldoer er inkluderet og summen af Merkle-træet. 

I tilfældet med en børs' reserver ønsker vi at bevise 1:1-opbakning af kundernes saldi, uden at identifikatorer og saldi for hver konto offentliggøres. Derudover gør zk-SNARK-teknologien det endnu mere usandsynligt at forfalske data.

Hvad er et Merkle-træ?

At præsentere de summerede midler på Binance-brugernes konti kræver, at man arbejder med et stort datasæt. En måde at præsentere denne store mængde data kryptografisk på er at bruge et Merkle-træ. En stor mængde oplysninger kan lagres i det på effektiv vis, og dets kryptografiske natur gør det nemt at verificere dets integritet.

Hash-funktioner

For kortfattet at kode et input afhænger et Merkle-træ af brugen af hash-funktioner. Hashing refererer kort sagt til processen med at generere et output i fast størrelse fra et input af variabel størrelse. Med andre ord, når et input af en hvilken som helst længde hashes gennem en algoritme, vil det producere et krypteret output af fast længde.

Så længe inputtet forbliver det samme, vil outputtet også gøre det. Det betyder, at vi kan tage enorme mængder transaktionsdata og hashe dem til et håndterbart output. Outputtet vil være radikalt anderledes, hvis nogen oplysninger ændres i inputtet.

Vi kan f.eks. tage indholdet af 100 bøger og indtaste dem i SHA-256-hashfunktionen. Det ville dermed resultere i noget i retningen af dette som output:

801a9be154c78caa032a37b4a4f0747f1e1addb397b64fa8581d749d704c12ea

Hvis vi så ændrer et enkelt tegn i inputtet (de 100 bøger), vil hashen være helt anderledes, sådan her:

abc5d230121d93a93a25bf7cf54ab71e8617114ccb57385a87ff12872bfda410

Det er en vigtig egenskab ved hash-funktioner, fordi det gør det nemt at verificere dataenes nøjagtighed. Hvis nogen gentager processen med at hashe de samme 100 bøger ved hjælp af SHA-256-algoritmen, vil de få nøjagtig den samme hash som output. Hvis outputtet er anderledes, kan vi med sikkerhed sige, at inputtet er blevet ændret. Det betyder, at der ikke er behov for individuelt eller manuelt at kontrollere forskelle mellem inputtene, hvilket kan være arbejdskrævende.

Merkle-træer i kryptovalutaens verden

Når man opbevarer transaktionsdata på en blockchain, indsendes hver ny transaktion gennem en hashfunktion, som genererer unikke hashværdier. Forestil dig, at vi har otte transaktioner (A til H), som vi hasher individuelt for at få deres hashede output. Det er dem, vi kalder Merkle Leaf-noderne. På billedet nedenfor kan du se den unikke hashværdi for hvert bogstav: hA for A, hB for B, hC for C osv.

Vi kan så tage par af hashede outputs, kombinere dem og få et nyt hashet output. Hashes af hA og hB hashet sammen vil f.eks. give os et nyt hashet output af hAB kendt som en Merkle-gren. Bemærk, at hver gang et nyt output genereres, har det en fast længde og størrelse i henhold til den anvendte hashfunktion.

Nu har vi data fra to transaktioner (f.eks. A og B) kombineret i én hash (hAB). Bemærk, at hvis vi ændrer nogen oplysninger fra A eller B og gentager processen, vil vores hashede output hAB være helt anderledes.

Processen fortsætter, når vi kombinerer nye par af hashes for at hashe dem igen (se billedet nedenfor). Vi hasher hAB med hCD for at få en unik hash hABCD og gør det samme med hEF og hGH for at få hEFGH. I sidste ende modtager vi en enkelt hash, der repræsenterer de hashede output af alle tidligere transaktioners hash. Med andre ord repræsenterer det hashede output hABCDEFGH alle de oplysninger, der kom før det.

Grafen, der vises ovenfor, kaldes et Merkle-træ, og det hashede output hABCDEFGH er Merkle-roden. Vi bruger Merkle-rødder i block headers, da de kryptografisk opsummerer alle transaktionsdata i en blok på en kortfattet måde. Vi kan også hurtigt verificere, om der er blevet manipuleret med eller ændret data i blokken.

Begrænsningerne ved Merkle-træer

Lad os vende tilbage til vores eksempel med CEX-reserver. En CEX ønsker at bevise 1:1-opbakning af alle sine kunders aktiver og bygger et Merkle-træ, der hasher sine kunders UID'er sammen med deres nettoaktivbeholdninger (modregning af aktiver og passiver) på tokenniveau. Når det er frigivet (og signeret for at bevise ejerskab over Merkle-roden), vil en individuel bruger ikke have nogen mulighed for at kontrollere, om Merkle-træet er gyldigt uden at få adgang til alle dets inputs.

En børs kan have overset at inkludere nogle inputs. Den kan også oprette falske konti med negative saldi for at ændre det samlede ansvar. Selvom kundernes aktiver f.eks. kan være på 1.000.000 USD, kan der tilføjes en falsk konto med en saldo på -500.000 USD. Det ville skabe et reservemål på blot 500.000 USD.

Beviset for reserver er forskelligt fra en bloks Merkle-rod, da brugere kan se alle de transaktioner, en blok indeholder, på en blockchain-udforsker. En CEX ønsker dog ikke at afsløre hver enkelt kontosaldo af hensyn til sikkerhed og databeskyttelse. Kunderne ville heller ikke være glade for, at deres kontosaldi blev offentliggjort. I dette tilfælde kan CEX'en ikke bevise, at brugersaldi summerer til den korrekte sum uden at gøre andre brugersaldi synlige.

En løsning, som børser kan overveje at anvende, er at bruge en betroet tredjepartsrevisor. Revisoren kan kontrollere de enkelte konti og reserver, før denne endeligt attesterer gyldigheden af den leverede Merkle-rod. Men for brugerne kræver denne metode tillid til revisoren og de data, der bruges til revisionen. Du behøver ikke at forlade dig på en tredjepart, når du kan stole på dataene.

Kombination af zk-SNARK'er med Merkle-træer

Ovenstående problem er et perfekt eksempel på brug af zk-SNARK'er. Vi ønsker at bevise, at reserverne fuldt ud dækker brugernes forpligtelser og ikke er forfalskede. Men af hensyn til beskyttelse af personoplysninger og sikkerhed ønsker vi ikke at vise verifikatoren den nøjagtige sammensætning af brugernes saldi og reserver. 

Ved at bruge en zk-SNARK kan en kryptobørs bevise, at alle Merkle-træets blad-noders saldosæt (dvs. brugerkontosaldi) bidrager til børsens påståede samlede brugeraktivsaldo. Hver bruger kan nemt få adgang til sin blad-node, som har været inkluderet i processen. zk-SNARK'en sikrer også, at ethvert Merkle-træ, der genereres, ikke indeholder brugere med en negativ samlet nettoaktivsaldo (hvilket ville betyde forfalskning af data, da alle lån er oversikkerhedsstillede). Der bruges også en beregning af Binances globale tilstand, dvs. en liste over den samlede nettosaldo for hvert aktiv, som hver Binance-kunde har.

Lad os tage et kig på, hvordan Binance griber situationen an. Til at begynde med definerer Binance begrænsningerne for den beregning, den ønsker at bevise, og definerer dem som et programmerbart kredsløb. Nedenfor er de tre begrænsninger, som Binance bruger i sin model. 

For hver brugers saldosæt (Merkle-træets blad-node) sikrer vores kredsløb, at:

  1. En brugers aktivsaldi er inkluderet i beregningen af summen af en brugers samlede nettosaldo hos Binance.

  2. Brugerens samlede nettosaldo er større end eller lig med nul.

  3. Ændringen af Merkle-træets rod er gyldig (dvs. bruger ikke forfalskede oplysninger) efter opdatering af en brugers oplysninger til blad-nodens hash.

Binance kan derefter generere et zk-SNARK-bevis for Merkle-træets konstruktion i henhold til kredsløbet. Dette indebærer, at børsen udfører den tunge beregning af hashing af brugernes id'er og saldi, samtidig med at den sikrer, at beviset består begrænsningerne.

En verifikator vil undersøge beviset (og dets offentligt frigivne open source-kode) for at blive overbevist om, at beregningen udføres med alle begrænsninger opfyldt. Verifikationsberegningen tager ekstremt kort tid sammenlignet med bevistiden.

Ved hver udgivelse af Proof of Reserves vil børsen offentliggøre:

1. Merkle-beviset for hver bruger.

2. zk-SNARK-beviset og det offentlige input (en hash af listen over den samlede nettosaldo for hvert aktiv og Merkle-roden) for kredsløbet for alle brugere.

Interesserede parter kan verificere Merkle-beviset og sikre, at deres individuelle saldi har bidraget til Merkle-træets rod. De kan også verificere zk-SNARK-beviset for at sikre, at konstruktionen af Merkle-træet opfylder de begrænsninger, der er defineret i kredsløbet. For en mere detaljeret forklaring af zk-SNARK-løsningen og dens ydeevne henvises der til vores blog Sådan forbedrer zk-SNARK'er Binances Proof of Reserves-system.

Sammenfatning

zk-SNARK'er leverer den teknologi, der er nødvendig for at sikre både dataintegritet og beskyttelse af personoplysninger på samme tid. Dens anvendelse til at bevise reserver og øge CEX-transparens bør hjælpe med at opbygge tillid til blockchain-branchen. For mange har en udvikling som denne været længe ventet og kommer på et afgørende tidspunkt for CEX'er.

Dette er den første version af vores zk-SNARK, og vi ser frem til at modtage feedback fra fællesskabet, så vi kan fortsætte med at forbedre systemet.

Yderligere læsning