aes
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| aes [2023/12/07 16:26] – kresimir | aes [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 123: | Line 123: | ||
| 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 " | 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 " | ||
| 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. | 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č** | ||
| + | |||
| + | < | ||
| + | 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 ciphertext, djelomični plaintext te program koji se koristio za šifriranje poruke, | ||
| + | ali ne i tajni AES ključ. | ||
| + | |||
| + | Možeš li dešifrirati poruku? | ||
| + | </ | ||
| + | |||
| + | 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, | ||
| + | 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, | ||
| + | |||
| + | 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, | ||
| + | |||
| + | 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, | ||
| + | |||
| + | 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: | ||
| + | |||
| + | < | ||
| + | AES_EncryptInit(& | ||
| + | | ||
| + | | ||
| + | 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; | ||
| + | nonce_xor_counter[i] = nonce[i] ^ counter; | ||
| + | |||
| + | } | ||
| + | counter +=1; | ||
| + | AES_Encrypt(& | ||
| + | |||
| + | for(int i=offset; | ||
| + | ciphertext[i] = enc_output[i%16]^plaintext[i]; | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | output(" | ||
| + | |||
| + | </ | ||
| + | |||
| + | Ranjivost implementacije je u tome da se za varijablu brojača (// | ||
| + | |||
| + | 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, | ||
| + | |||
| + | 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 259. bloka | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
aes.1701966364.txt.gz · Last modified: 2025/12/01 11:40 (external edit)