User Tools

Site Tools


aes

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
aes [2023/11/23 07:21] zrinkaaes [2025/12/01 11:40] (current) – external edit 127.0.0.1
Line 35: Line 35:
  
 **2) CBC (Cipher Block Chaining)** **2) CBC (Cipher Block Chaining)**
-  * Svaki blok jasnog teksta se XOR-a sa skrivenim tekstom prošlo kruga enkripcije+  * Svaki blok jasnog teksta se XOR-a sa skrivenim tekstom prošlog kruga enkripcije
   * Potreban je inicijalizacijski vektor IV koji se mora izabrati nasumično   * Potreban je inicijalizacijski vektor IV koji se mora izabrati nasumično
   * IV se šalje zajedno sa skrivenim tekstom    * IV se šalje zajedno sa skrivenim tekstom 
Line 58: Line 58:
   *način autentifikacijskog kriptiranja koji je primjenjiv samo za simetrične blok algoritme s veličinom bloka od 128 bitova   *način autentifikacijskog kriptiranja koji je primjenjiv samo za simetrične blok algoritme s veličinom bloka od 128 bitova
   * samo za autentifikaciju – koristi [[mac|MAC]]   * samo za autentifikaciju – koristi [[mac|MAC]]
-  * ulaz: jasni tekst, IV, povezani autentifikacijski podaci (Associated Data, AD ), duljina povezanih podataka i duljina kriptiranog teksta+  * ulaz: jasni tekst, IV, povezani autentifikacijski podaci (Associated Data, AD), duljina povezanih podataka i duljina kriptiranog teksta
   * izlaz: autentifikacijska značka (Auth Tag)   * izlaz: autentifikacijska značka (Auth Tag)
 {{ ::gcm.png?nolink&500 | GCM shema}} {{ ::gcm.png?nolink&500 | GCM shema}}
Line 89: Line 89:
 </file> </file>
  
-Pokušajmo se spojiti na chal.platforma.hacknite.hr i port 8083. Imamo mogućnost pisanja, a kao rezultat dobijemo ispis kodiranog teksta koji smo unijeli. Upišimo jedno slovo, a zatim ponovimo to isto slovo tri puta da bismo vidjeli kako funkcionira kodiranje+U prilogu se nalazi i datoteka encrypt.py. 
 + 
 +Pokušajmo se spojiti na chal.platforma.hacknite.hr i port 8083. Imamo mogućnost pisanja, a kao rezultat dobijemo ispis kodiranog teksta koji smo unijeli. U encrypt.py datoteci. vidimo da se koristi AES ECB mod (linija 19: cipher = AES.new(key, **AES.MODE_ECB**)) te da se svaki znak jasnog teksta tretira kao zasebni blok. U ECB načinu rada se svaki isti blok jasnog teksta uvijek šifrira u isti ciphertext. Uvjerimo se da je zaista tako. Upišimo jedno slovo, a zatim ponovimo to isto slovo tri puta: 
  
 {{ :nc-a.jpg?600 |}} {{ :nc-a.jpg?600 |}}
  
-Vidimo da se šifrira svaki znak zasebno, što nam uvelike olakšava posaoUpišimo dio flaga koji znamo, a zatim i cijeli ciphertext da vidimo gdje u njemu počinje flag:+Vidimo da se svaka pojava istog znaka šifrira jednako, što i odgovara AES ECB moduSad upišimo dio flaga koji znamo, a zatim i cijeli ciphertext da vidimo gdje u njemu počinje flag:
  
 {{ :nc-ctf2022.png?600 |}} {{ :nc-ctf2022.png?600 |}}
Line 120: Line 122:
  
 Objasnimo što skripta radi. Kao podatak (//data//) uzeli smo dio zastavice koji nam je poznat. Nakon toga, dok ne dođemo do kraja flaga (znak "]"), uključujući i njega, //brute force// pogađamo koji je idući znak u skupu svih mogućih znakova koji se mogu pojaviti u flagu (brojevi i uglate zagrade). Svaki taj mogući znak kodiramo (funkcija //get_enc//) i, ako se kod poklapa s onime što slijedi u tekstu, znači da je taj znak idući i dodajemo ga na konačni flag. Funkcija get_enc jednostavno se spaja netcatom na stranicu zadanu u zadatku i ispisuje rezultat koji se dobije kodiranjem trenutnog znaka. Važno je napomenuti da uzima samo od indeksa 2 s početka do trećeg znaka od kraja jer python dodaje stringovima //b'// na početak stringa i //'\n// na kraj pa da se i ti znakovi ne kodiraju. \\ Objasnimo što skripta radi. Kao podatak (//data//) uzeli smo dio zastavice koji nam je poznat. Nakon toga, dok ne dođemo do kraja flaga (znak "]"), uključujući i njega, //brute force// pogađamo koji je idući znak u skupu svih mogućih znakova koji se mogu pojaviti u flagu (brojevi i uglate zagrade). Svaki taj mogući znak kodiramo (funkcija //get_enc//) i, ako se kod poklapa s onime što slijedi u tekstu, znači da je taj znak idući i dodajemo ga na konačni flag. Funkcija get_enc jednostavno se spaja netcatom na stranicu zadanu u zadatku i ispisuje rezultat koji se dobije kodiranjem trenutnog znaka. Važno je napomenuti da uzima samo od indeksa 2 s početka do trećeg znaka od kraja jer python dodaje stringovima //b'// na početak stringa i //'\n// na kraj pa da se i ti znakovi ne kodiraju. \\
-Zakomentirani printovi služe za bolje razumijevanje skripte. Poželjno je dodati //sleep()// između svake iteracije petlje kako stranica ne bi primijetila velik broj zahtjeva u kratkom vremenu, ali nije potrebno za ovaj zadatak.+Zakomentirani printovi služe za bolje razumijevanje skripte. Poželjno je dodati //sleep()// između svake iteracije petlje kako se poslužitelj ne bi preopteretio prevelikim brojem zahtjeva
 + 
 +__PRIMJER__ -**Zadatak s Hacknite platforme - Brojač** 
 + 
 +<file> 
 +Mnogi od vas već znaju da je AES ECB način rada nesiguran.  
 +Zato smo odlučili šifrirati tajnu poruku koristeći AES CTR način rada.  
 +Dostupan ti je ciphertextdjelomični plaintext te program koji se koristio za šifriranje poruke,  
 +ali ne i tajni AES ključ. 
 + 
 +Možeš li dešifrirati poruku? 
 +</file> 
 + 
 +Ideja zadatka jest pronaći ranjivost u AES implementaciji s CTR načinom rada. 
 +CTR način rada jest definiran sljedećom formulom za enkripciju: 
 + C = P ⊕ AES(key,CTR) 
 +gdje je C ciphertext, P plaintext, a CTR kombinacija nonce vrijednosti (neka nasumična vrijednost) i brojača (u našoj implementaciji su kombinirani pomoću XOR operacije). Funkcija AES ovdje ne šifrira sam plaintext, nego CTR vrijednost koja se zatim XOR-a s plaintextom. Rezultat funkcije AES(key,CTR) zovemo **keystream**. 
 + 
 + Ne šifrira se cijeli plaintext odjednom već se radi u blokovima od 16 bajtova. Prvi ciphertext 
 +blok jest veličine 16 te je nastao xoranjem keystreama (za prvu iteraciju) s prvim blokom (također 16 bajtova) plaintexta, drugi ciphertext xoranjem keystreama 
 +(za drugu iteraciju) s drugim blokom plaintexta itd... 
 +U odnosu na CBC način rada, gdje se svaki novi blok xora s prijašnjim, CTR-om nastali blokovi nisu međusobno ovisni. 
 + 
 +AES je funkcija koja prima dva parametra, key i CTR. CTR jest kombinacija noncea i countera. Nonce jest fiksna vrijednost koja se nikada ne mijenja tijekom enkripcije 
 +i dekripcije svih blokova, a counter jest vrijednost koja se inkrementira sa svakom novom iteracijom (krećući od 0 u implementaciji). Key jest tajna koja se koristi za enkripciju i  
 +dekripciju te se također nikada ne mijenja. AES je funkcija koja interno ne koristi randomizirane vrijednost jer dekripcija ne bi bila moguća. 
 +Proces dekripcije je opisan sljedećom formulom (suprotan proces od enkripcije): 
 + P = C ⊕ AES(key,CTR) 
 + 
 +Dakle, kako bi dekripcija bila moguća, za isti broj iteracije enkripcije i dekripcije koristi se isti keystream. 
 + 
 +U ZIP datoteci priloženoj uz zadatak dan je algoritam za enkripciju, cijeli ciphertext te parcijalni plaintext. Proučavanjem ciphertext datoteke vidimo da se ciphertext sastoji od 4160 bajtova (260 blokova), a u plaintext datoteci se nalazi 4138 bajtova. Budući da se jedan blok sastoji od 16 bajtova, možemo zaključiti da 
 +imamo cijeli plaintext do 257. bloka (bitno je zapamtiti da brojimo od nule!) , pola 258. bloka, a uopće nemamo 259. blok. 
 + 
 +Dakle, moramo pronaći način da dešifriramo 258. i 259. blok ciphertexta. 
 + 
 +Kod za enkripciju unutar encrypt.c jest sljedeći: 
 + 
 +<file> 
 + AES_EncryptInit(&ctx, key);  
 +      
 +      
 +     unsigned char counter = 0; 
 + 
 +     for (unsigned int offset = 0; offset < (4160); offset += AES_BLOCK_SIZE) { //CTR mode 
 + unsigned char nonce_xor_counter[AES_BLOCK_SIZE]; 
 + unsigned char enc_output[AES_BLOCK_SIZE]; 
 + for(int i=0;i<16;i++){ 
 +     nonce_xor_counter[i] = nonce[i] ^ counter; 
 + 
 +
 + counter +=1; 
 + AES_Encrypt(&ctx, nonce_xor_counter, enc_output); 
 + 
 + for(int i=offset;i<(offset+AES_BLOCK_SIZE);i++){  
 +     ciphertext[i] = enc_output[i%16]^plaintext[i]; 
 + 
 +
 +     } 
 + 
 +     output("\nEncrypted: 0x", ciphertext, (4160)); 
 + 
 +</file> 
 + 
 +Ranjivost implementacije je u tome da se za varijablu brojača (//counter//) koristi tip podatka char . Char jest veličine bajt, odnosno prima vrijednosti 0-255.  
 + 
 +Zbog toga, nakon vrijednosti 255 inkrementiranjem nastaje [[integer|integer overflow]] te se vrijednost resetira na 0. To znači da je counter za iteraciju 258/259 zapravo 2/3 što onda znači da je keystream za navedene parove iteracija isti. 
 + 
 +Budući da imamo ciphertext i parcijalni plain text, moguće je doći do keystreama po formuli: 
 + C ⊕ P = AES(key,CTR) 
 + 
 +U nastavku se prikazuje postupak kojim se dolazi do rješenja, bitno je zapamtiti da brojač počinje od nule! 
 + 
 + plaintext[2] ⊕ ciphertext[2] = keystream [2] 
 + keystream[258] = keystream[2] // zbog integer overflowa, keystream kojim se šifrirao 258. blok jednak je onom kojim se šifrirao 2. blok 
 + plaintext[258] = keystream[258] ⊕ ciphertext[258] // ovako dobivamo plaintext 258. bloka 
 + 
 + // zatim ponovimo postupak za 259. blok 
 + 
 + plaintext[3] ⊕ ciphertext[3] = keystream [3] 
 + keystream[259] = keystream[3] // zbog integer overflowa, keystream kojim se šifrirao 259. blok jednak je onom kojim se šifrirao 3. blok 
 + plaintext[259] = keystream[259] ⊕ ciphertext[259] // ovako dobivamo plaintext 259bloka 
 + 
 + 
 + 
 + 
 + 
 + 
  
  
aes.1700724066.txt.gz · Last modified: 2025/12/01 11:40 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki