--- title: Så fungerar det nav: How it works output: how-it-works/index.html description: Så fungerar Varsto: dina enheter och dina egna lagringsplatser, krypterade block, nycklar, den signerade liggaren som håller reda på varje kopia, synkronisering, peer-to-peer-överföring, delning, Strongroom och återställningspaketet, med de ärliga begränsningarna. ---
Tekniken bakom Varsto, en mekanism i taget: hur en fil blir krypterade block, vilka nycklar som finns, hur den signerade liggaren håller reda på varje kopia, hur enheter synkroniserar och hittar varandra, och vad som ännu inte är klart.
Allt här är implementerat i kärnan, vars källkod är tillgänglig (crates/varsto-core), och beskrivs med exakta fältlayouter i lagringsformatet. Det är alfaprogramvara: formaten kan fortfarande ändras, och varken designen eller koden har granskats. Hotmodellen och felmodellen beskriver vad den skyddar mot och inte.

Varsto består av två sorters delar, och inget av vårt däremellan.
Varje lagringsplats rymmer samma tre sorters objekt: krypterade block med filinnehåll, varje enhets krypterade fillistor (manifest) och varje enhets signerade liggare, plus några små krypterade poster för enheter, mappar och regler. Varje sökväg har exakt en skrivare: en enhet skriver bara under sitt eget id, och block namnges efter hashvärdet av sin chiffertext och skrivs aldrig över. Lagringsplatserna behöver därför inga lås, och var och en fungerar också som brevlåda: enheter som aldrig är online samtidigt blir ändå samstämmiga, så länge de delar en lagringsplats. Enheter kan också utbyta block direkt, i det lokala nätverket eller över internet.
Det finns inget Varsto-konto, ingen server och inget relä. Om projektet upphörde i morgon skulle dina installerade enheter fortsätta synkronisera via dina lagringsplatser.

fsck --verify och den automatiska verifieringen kontrollerar kopior de inte kan läsa.Känd avvägning: deterministisk (konvergent) kryptering inom en mapp innebär att två personer som båda har mappnyckeln kan avgöra om de har en identisk fil, och de komprimerade bitarnas storlekar syns för lagringsplatsen. I en delad mapp gäller det under en nyckelepok; när en medlem tas bort får mappen en ny slumpmässig nyckel, så en borttagen medlem kan inte känna igen något som skrivs därefter.

Allt utgår från en enda slumpmässig 256-bitars valvnyckel, som skapas på den första enheten och aldrig härleds ur något du skriver. Den är den enda hemligheten att ta vara på; återställningspaketet är den nyckeln på papper.
keys.enc, krypterade under en nyckel som Argon2id härleder ur enhetens lösenfras. Att byta lösenfras krypterar om den filen och rör ingenting på lagringsplatserna.När en enhet tas bort inleds en ny nyckelepok: en ny slumpmässig valvnyckel, förseglad till var och en av de kvarvarande enheterna med det hybrida nyckelutbytet nedan. Nya liggarbatcher, poster, fillistor och block använder de nya nycklarna, och en kedja av krypterade epokposter låter den nya nyckeln öppna allt äldre. Den borttagna enheten hittar en signerad återkallelse nästa gång den når en lagringsplats och slutar; med en raderingsorder tömmer den också sina mappar och nycklar.
| Ändamål | Algoritm | Anmärkningar |
|---|---|---|
| Kryptering av innehåll och metadata | XChaCha20-Poly1305 (AEAD) | 256-bitars nycklar, 192-bitars nonces. Varje chiffertext bär associerade data som anger vad den är, så en lagringsplats kan inte flytta ett objekt till en annan roll. |
| Hashning och nyckelhärledning | BLAKE3 (nyckelad hash och derive_key) | Bit-id:n och filhashar är nyckelade. Varje härledd nyckel bär kontexten e2ee-sync-format/0/<purpose>. |
| Från lösenfras till nyckel | Argon2id | Minst 64 MiB, 3 pass; ett slumpmässigt salt per enhet. Lösenfrasen lämnar aldrig enheten. |
| Signaturer (liggare, poster) | Ed25519 + ML-DSA-65, hybrid | Båda signaturerna täcker samma byte och båda måste verifieras. En nyckel med en postkvantdel godtar aldrig en signatur med enbart Ed25519. |
| Nyckelutbyte (delning, nya epoker) | X25519 + ML-KEM-768, hybrid | Båda delade hemligheterna och hela transkriptet går in i en nyckel; en förseglad hemlighet förblir privat om inte båda algoritmerna knäcks. |
| Mappar med säkerhetsnyckel | FIDO2 hmac-secret | Säkerhetsnyckeln härleder en 32-byte hemlighet ur en credential och ett salt per mapp efter en beröring. |
| Återställningspaket | BIP-39-ord, Shamir över GF(256) | 24 ord med kontrollsumma; valfritt 2-av-3-andelar. |

Liggaren är Varstos bokföring. Varje enhet för sin egen logg över fakta som bara kan läggas till om vad den har gjort, och ingen enhet skriver någonsin i en annans logg. Fakta är små och konkreta: ”Jag skrev block 7f3a till lagringsplatsen jag kallar box”, ”Jag laddade ner 7f3a från box och hashvärdet stämde”, ”Jag publicerade version 12 av den här mappens fillista”.
Varje enhet läser alla andra enheters loggar via lagringsplatserna och spelar upp dem alla till samma bild: vilka block som finns, var varje kopia finns, vem som skrev den, vem som har kontrollerat den och när. Inget i den betros på grund av var det kom ifrån: varje batch är signerad av enheten som skapade den, och en kopia räknas som verifierad först när en annan enhet har kontrollerat den.
Utan liggaren kan ett synkroniseringsverktyg bara hoppas att dess kopior finns. Med den kan Varsto säga hur många kopior av varje block som finns, på vilka platser, hur nyligen var och en kontrollerades och vilka ingen har kontrollerat än.
| Händelse | Betydelse |
|---|---|
| Enhet registrerad | Den här enheten anslöt till valvet, under det här namnet. |
| Mapp tillagd | Den här enheten skapade en mapp. |
| Block lagrat | Den här enheten skrev ett krypterat block till en lagringsplats: mapp, bit-id, objektnamn, storlek och lagringsplats. Ett påstående som bara intygas av skrivaren. |
| Block verifierat | Den här enheten laddade ner blocket från en lagringsplats och hashvärdet stämde med namnet. Registreras vid nedladdningar, fsck --verify, automatisk verifiering och fullständiga diskkontroller. |
| Block på enhet | Den här enheten har blockets klartext, som del av en fil. |
| Fillista publicerad | Den här enheten publicerade version n av en mapps fillista, med dess hash och antal filer. |
| Lagringsplats avvecklad | En lagringsplats togs bort från valvet: påståenden om den som gjorts före den här händelsen räknas inte längre som kopior. |
Inga filnamn och inget innehåll: block identifieras med nyckelade bit-id:n och chiffertexthashar, och hela batchen är dessutom krypterad.

Händelser samlas i batcher, vanligen en per synkronisering snarare än en per fil. En batch bär enhetens id, ett sekvensnummer (1, 2, 3, ...), hashen av enhetens föregående batch, en logisk klocka, när den skapades och händelserna.
ledger/<device>/<sequence>, och skrivs aldrig över.En läsare godtar en batch bara när båda signaturerna verifieras mot enhetens publika nyckel i enhetsregistret och dess föregående hash stämmer. Postkvantsignaturen kostar ungefär 3,3 KB, och därför färdas händelserna i batcher: liggaren växer med några kilobyte per synkronisering, inte per fil.
Varje lagringsplats är en brevlåda. När en enhet har sparat en batch laddar den upp alla egna batcher som en lagringsplats saknar; vid varje hämtning listar den liggaren på varje varm lagringsplats, tar de batcher den inte har sett, kontrollerar dem, dekrypterar dem och behåller en lokal kopia. Eftersom varje lagringsplats bär hela liggaren ser en bärbar dator som synkroniserar på natten och en telefon som synkroniserar på morgonen samma historik utan att någonsin mötas. Ingen ordnar något centralt: en logisk klocka (Lamport) ordnar ändringarna, inte väggklockan. Opålitliga repliker och de personer du delar en mapp med skriver också liggare, förseglade under nycklar som bara öppnar deras del: en repliks påståenden anger objekt, inte filer, och en medlems påståenden gäller bara den delade mappen.
När alla batcher spelas upp får varje enhet samma vy: för varje block i varje mapp dess objektnamn och storlek, de lagringsplatser som påstår sig ha en kopia och vilken enhet som påstod det, vilka enheter som verifierade det där och när, och vilka enheter som har klartexten. Den känner också till varje enhets senaste fillista för varje mapp, vilka enheter och mappar som finns och vilka lagringsplatser som är avvecklade. Lagringsplatsernas namn är lokala för varje enhet (”box” här, ”primary” där), så varje lagringsplats bär en slumpmässig identitet, och enheterna matchar varandras påståenden med den.
fsck. Jämför liggaren med vad lagringsplatserna faktiskt listar: påståenden utan objekt, block utan kopia någonstans, block som verifierats på annat håll.Eftersom varje enhet numrerar och kedjar sina egna batcher kan historiken inte skrivas om i det tysta. Två olika batcher med samma enhet och sekvensnummer, eller en batch vars föregående hash inte stämmer, är en förgrening: varje enhet som ser en sådan markerar enheten som förgrenad, och fsck rapporterar det. Den vanliga orsaken är en enhet som återställts från en gammal säkerhetskopia eller en klonad disk, som skulle fortsätta från ett sekvensnummer som dess nyare jag redan har använt. När en enhet hittar batcher under sin egen identitet som den aldrig skrivit spärrar den sig själv: den slutar signera och skicka tills den registreras på nytt som en ny enhet, så att två divergerande kopior av en identitet aldrig båda skriver historik.
Liggaren säger var blocken finns; manifesten säger vad filerna är. Efter en ändring publicerar en enhet hela sin bild av en mapp som ett nytt manifest: varje sökväg med storlek, ändringstid, innehållshash, blocklista och en versionsvektor (för varje enhet klockan för dess senaste ändring). Det krypteras under mappens metadatanyckel och annonseras i liggaren. Andra enheter hämtar de manifest de inte har sett och slår samman dem sökväg för sökväg:
name.conflict-<device>-<clock>.ext, så att båda enheterna blir samstämmiga utan ytterligare en runda.Raderade filer hamnar i en lokal papperskorg och tas aldrig bort direkt. Bakgrundstjänsten bevakar dina mappar och synkroniserar inom några sekunder efter en ändring. Selektiva mappar visar alla filer men behåller platshållare för dem du inte har hämtat, och hämtar en fil när du öppnar den. Manifesten är i dag fullständiga vyer; mycket stora mappar kommer att behöva inkrementella.
Enheter utbyter också block direkt. Eftersom krypteringen är deterministisk inom en mapp kan en enhet som har en fil leverera exakt det objekt som lagringsplatsen har, och mottagaren kontrollerar det mot namnet precis som en kopia från en lagringsplats. En enhet som behöver ett block frågar först sina peers och sedan lagringsplatserna, och fördelar på varandra följande block över de peers som svarar.
Testat på localhost, i underhållarens egna nätverk och i en uppställning med tre enheter bakom olika NAT. Två symmetriska NAT kan inte genomslås och faller tillbaka på ett relä, vilket kräver en nåbar enhet i valvet (en hemserver, en VPS, en vidarebefordrad port); socketar stöder bara IPv4.
Hur snabbt. Prestandatester mäter nedladdningar mellan Paris, Amsterdam och Warszawa, peer-to-peer jämfört med en S3-bucket, med metoden, siffrorna och vad som fortfarande är långsamt.
Transport och det lokala gränssnittet. Objekten är chiffertext innan de lämnar enheten, så transporten lägger inte till ett andra lager bara för sakens skull: S3 talas över HTTPS med Signature Version 4, rclone-remotes använder rclones egen konfiguration, och S3-hemligheten förvaras i en krypterad fil. Skrivbordsgränssnittet levereras bara på 127.0.0.1, varje förfrågan bär en sessionstoken, Host-huvudet kontrolleras och sidan körs under en strikt Content Security Policy.
| Part | Ser | Kan inte se |
|---|---|---|
| En lagringsleverantör (bucket, NAS, disk, rclone-remote) | Objektnamn (hashar av chiffertext), objektstorlekar, hur ofta du skriver och läser, ditt antal enheter utifrån antalet liggarkataloger. | Filnamn, innehåll, mappnamn, vilka block som hör till vilken fil, hashen av din klartext. |
| En opålitlig replik (en väns NAS) | Samma som en lagringsleverantör, plus att objekten stämmer mot sina namn. Den signerar sina egna påståenden under en nyckel som bara gäller repliken. | Något innehåll, namn eller någon fillista; den får aldrig en mappnyckel eller valvnyckeln. |
| En peer i det lokala nätverket eller på internet | Att någon enhet begär objekt efter namn, efter att ha bevisat att den har valvets nyckel för peer-autentisering. | Något alls utan den nyckeln: en främling får inget objekt, och beaconen i det lokala nätverket namnger inte valvet. |
| Någon du delar en mapp med | Den mappen: varje fil i den, och dina enheters signerade påståenden om den. | Någon annan mapp, valvnyckeln, ditt enhetsregister. |
| En AI-assistent via MCP-servern | De mappar du gav åtkomst till, med enbart läsrätt om du inte sade annat. | Mappar du inte gav åtkomst till; Strongroom-mappar, aldrig. |
| En tjuv med din upplåsta bärbara dator | Allt som en vanlig mapp innehåller medan enheten är upplåst. | Strongroom-mappar utan din säkerhetsnyckel; inget som skrivits efter att du tagit bort enheten från en annan, utom i mappar som delas med andra personer. |

Mottagarens enhet skapar ett hybridnyckelpar (X25519 + ML-KEM-768) och skriver ut en förfrågningskod med den publika halvan. Din enhet kapslar in mot båda halvorna, härleder en nyckel ur båda delade hemligheterna och transkriptet, och krypterar mappnyckeln med den. Den resulterande token kan skickas via vilken kanal som helst: bara den begärande enheten kan öppna den, och den öppnar en mapp.
Innan förseglingen jämför ni båda ett fingeravtryck: sex ord som härleds ur förfrågningskoden och namnet i den. Ni läser upp dem för varandra i ett samtal eller personligen; en kod som bytts ut på vägen ger andra ord, och mottagarens enhet vägrar en token vars bekräftade ord inte är dess egna.
Mottagarens enhet skriver sedan sin egen liggare för den mappen, förseglad under en nyckel som härleds ur mappnyckeln: båda sidor ser varandras påståenden för den mappen och inget annat. När en medlem tas bort, eller en token som ingen ännu har godtagit återkallas, får mappen en ny slumpmässig nyckel: dina enheter och de medlemmar som stannar kvar får den (förseglad till varje medlems egen nyckel), allt som skrivs därefter använder den, och den borttagna medlemmens senare ändringar ignoreras. Det de redan har fått förblir läsbart för dem; en nyckel kan inte kallas tillbaka.

En Strongroom-mapps nyckel finns aldrig i vila. När mappen skapas gör säkerhetsnyckeln en credential och tar sedan fram en 32-byte hemlighet ur den och ett slumpmässigt salt per mapp (FIDO2 hmac-secret). Varsto slår in mappnyckeln under den hemligheten och lagrar bara credential-id, saltet och den inslagna nyckeln. Upplåsning upprepar beröringen och håller nyckeln i minnet under en tidsperiod (15 minuter som standard) och glömmer den sedan. Det finns ingen väg till mappnyckeln utan den fysiska nyckeln: inte via lösenfrasen, valvnyckeln eller en stulen säkerhetskopia. Reservsäkerhetsnycklar får sin egen inslagning av samma mappnyckel. Att konvertera en befintlig mapp ger den ett nytt id och en ny nyckel, krypterar om den och raderar den gamla chiffertexten; att byta nyckel för ett Strongroom gör detsamma med en ny nyckel inslagen för varje registrerad säkerhetsnyckel, för de fall då någon kan ha behållit en nyckel.

Enhetens lösenfras går genom Argon2id för att låsa upp keys.enc; bakgrundsappen kan förvara den i operativsystemets nyckelring så att tjänsten låser upp sig själv efter inloggning. Att förlora en lösenfras innebär att förlora den enhetens kopia av nycklarna, inte valvet: en annan enhet, eller återställningspaketet, registrerar en ny.
Återställningspaketet skriver ut valvnyckeln som 24 BIP-39-ord (ett felskrivet ord fångas av kontrollsumman) och, om du vill, tre Shamir-andelar av vilka två valfria återskapar nyckeln medan en ensam inte avslöjar något. Det finns inget konto, ingen deponering och ingen återställning av lösenord: paketet är hur du bär ansvaret. Skriv ut ett nytt paket efter att du tagit bort en enhet, eftersom det gamla innehåller den gamla nyckeln.
Detaljer på fältnivå, bytelayouter och versionsregler: lagringsformat, nyckelhierarki, anteckningar om liggarsignering, säkerhetsprinciper, felmodell.