INDA25PlusPlus

Allmän information, slides och uppgifter

View the Project on GitHub INDA25PlusPlus/info

Uppgift 9 - Kryptografi

Uppgifter

Skapa ett repo i ++ organizationen som heter kth-id-cryptography där ni lägger all kod.

Läxan är att utveckla ett enkelt krypterat remote fillagringssystem i grupper av 2. Vi vill ha följande features:

* Vi vill inte att det ska avslöjas om vi krypterar samma fil två gånger.

** Potentiell attack om vi inte gör detta: säg att det är backuper vi lagrar, och en ond server byter ut en fil som körs vid startup mot malign kod från webbläsarcachen. Accessmönster skulle kunna användas för att ta reda på var dessa filer finns lagrade, utan att faktiskt behöva dekryptera dem.

Den sistnämnda punkten är antagligen den mest intressanta. Ett sätt vi skulle kunna göra det på är att låta klienten spara den senaste hashen av alla lagrade filer, och då och då begära ut slumpmässiga filer och se att deras hashar överensstämmer. Det kräver dock att vi lagrar en hash för varje fil, vilket tar för mycket minne – vi skulle helst vilja ha en klient som bara lagrar en konstant mängd data. För att komma runt detta använder vi oss av hashar av hashar, i form av ett Merkle-träd.

Sättet det fungerar på att är vi placerar ut filerna som lövnoder i ett binärt träd på servern, lagrar h[x] = H(x.data) för dem för något lämpligt val av hashfunktion H, och för alla icke-lövnoder lagrar h[x] = H(h[x.left] + h[x.right]). Vi kan därefter använda h[rotnod] som en hash av hela trädet, som lagras lokalt på klienten. När vi frågar om en fils data kan servern ge tillbaka den datan tillsammans med komplementerande hashar uppåt i trädet, som tillåter klienten att verifiera att hashen av hela trädet är korrekt (illustration). Skrivningar kan göras på motsvarande sätt: servern skickar över komplementerande hashar som klienten kan verifiera och använda för att uppdatera sin lokala rotnodshash. Eftersom vi har ett välbalancerat binärt träd krävs bara att ett logaritmiskt antal hashar skickas över/uppdateras i varje steg.

Det är lite överlapp i funktion mellan Merkleträdet och punkt 4 (signering av filer) – båda verifierar att filer är korrekta. För att undvika upprepat arbete skulle man kunna skippa punkt 4, eller låta h[x] = x.signatur för lövnoderna.

Ni får själva avgöra vilka krypterings-, signerings- och hashningsalgoritmer som är lämpliga. Beskriv valen lite kort i er README.

Ni har full frihet i detaljerna kring systemet, t.ex. programmeringsspråk, hur ni gör klient-server-kommunikation, o.s.v. En detalj som är värd att nämna är fil-id:na – för att göra saker enkelt kan det vara rimligt att låta dem vara tal mellan 0 och 2^n-1 för något litet fixerat tal n, så att vi får perfekta binära träd. Om ni däremot vill låta dem vara godtyckligt stora tal eller hashar av filnamn och få lata eller självbalancerande träd, go for it. Se längre ner för lite roliga möjliga vidareutvecklingar.


En steg-för-steg-beskrivning, ifall det hjälper att utgå från:

Utökningar

Material

Kryptobibliotek:

För hashning brukar det flyta runt public domain single file-bibliotek på internet, som också är okej att använda (till skillnad från asymmetrisk krypto och AES är hashning svårt att felimplementera).

Läsning

AEAD (authenticated encryption with associated data)

Kul läsning om kryptosårbarheter:

Praktiska tips för om ni behöver göra krypto:

http://latacora.singles/2018/04/03/cryptographic-right-answers.html beskriver det här mer utförligt (motiveringar, fler sorter av kryptoprimitiver, och antagligen ännu bättre råd). https://download.libsodium.org/doc/ är biblioteket som frekvent refereras till däri (som gör det mesta rätt rent kryptomässigt, även om man sen kanske inte vill använda C-API:erna rakt av).


Det finns en hel del bra bloggar om krypto, ofta så som det utövas i praktiken:

Wikipedia-länkar:

Finns bra böcker om krypto också (“crypto books” verkar ge vettiga träffar på Google), och kan rekommendera kursen DD2448 på KTH (går på våren, kräver möjligen diskmatte som förkunskap).