aes
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| aes [2023/11/20 10:07] – zrinka | aes [2025/12/01 11:40] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====AES==== | ====AES==== | ||
| - | **AES (Advanced Encryption Standard)**, | + | **AES (Advanced Encryption Standard)**, |
| {{ : | {{ : | ||
| AES koristi fiksnu veličinu bloka od 128 bitova te veličinu ključa od 128, 192 ili 256 bitova. Provodi se nad matricom 4x4, odnosno nad pravokutnim nizom bajtova u 4 retka i 4 stupca. Na sličan način tretira se i ključ koji je pohranjen u 4 retka i N stupaca, gdje je N ovisan o veličini ključa i može biti 4,6 ili 8. AES se pri enkripciji koristi operacijama zamjene znakova, posmicanja redova, miješanja stupaca te dodavanja potključa.\\ | AES koristi fiksnu veličinu bloka od 128 bitova te veličinu ključa od 128, 192 ili 256 bitova. Provodi se nad matricom 4x4, odnosno nad pravokutnim nizom bajtova u 4 retka i 4 stupca. Na sličan način tretira se i ključ koji je pohranjen u 4 retka i N stupaca, gdje je N ovisan o veličini ključa i može biti 4,6 ili 8. AES se pri enkripciji koristi operacijama zamjene znakova, posmicanja redova, miješanja stupaca te dodavanja potključa.\\ | ||
| 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 45: | Line 45: | ||
| * Slični protočnoj enkripciji, tj. jednokratnoj bilježnici | * Slični protočnoj enkripciji, tj. jednokratnoj bilježnici | ||
| * Dekripcija jednaka enkripciji | * Dekripcija jednaka enkripciji | ||
| - | * Trebalo bi svaki put koristiti različiti IV | + | * Trebalo bi svaki put koristiti različit inicijalizacijski vektor |
| {{ :: | {{ :: | ||
| Line 52: | Line 52: | ||
| * na temelju ključa i IV izračuna se niz bitova koji se XOR-a s jasnim tekstom | * na temelju ključa i IV izračuna se niz bitova koji se XOR-a s jasnim tekstom | ||
| * može se paralelizirati | * može se paralelizirati | ||
| - | * ne zahtijeva nadopunjavanje poruke (padding) | + | * ne zahtijeva nadopunjavanje poruke (eng. //padding//) |
| {{ :: | {{ :: | ||
| 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) | ||
| {{ :: | {{ :: | ||
| Line 65: | Line 65: | ||
| Generalno se ne preporučuje koristiti način kriptiranja ECB. Inicijalizacijski se vektor ne smije ponavljati i mora biti generiran slučajno, a ne smije se ponavljati ni simetrični ključ. | Generalno se ne preporučuje koristiti način kriptiranja ECB. Inicijalizacijski se vektor ne smije ponavljati i mora biti generiran slučajno, a ne smije se ponavljati ni simetrični ključ. | ||
| - | __PRIMJER__ -**Zadatak s Hacknite platforme - Encryption service** | + | __PRIMJER__ -**Zadatak s Hacknite platforme - AES kriptirana poruka** |
| < | < | ||
| - | Markov san bio je napraviti program koji će šifrirati nizove znakova. Spajanjem | + | Ivan je na faksu učio o modernim kriptografskim algoritmima. Toliko je očaran AES algoritmom da je odlučio |
| - | chal.platforma.hacknite.hr: | + | samostalno napraviti |
| - | možeš isprobati njegov | + | kako bi provjerio |
| - | pogoditi što je to Marko zapravo napisao? | + | |
| - | Tekst za šifriranje je: | + | ciphertext (u zasebnoj datoteci): |
| - | f44e2a4b2efd98c8b3d1b97c6da4649749ebb799d3c4a7c24bdfe3b36e0a35c6da15b0479f9912c0 | + | 991262a3123d702aaa296e36e4054dcb0031479d8affcae34dd12757b19868eee63f79e83e9687e10fc74dbd3c1a61bfdb4ec98a75 |
| + | 38f2c75eed1402d3edfd8dc28531c6d75a3786750afa0f48524d9adb4ec98a7538f2c75eed1402d3edfd8ddb4ec98a7538f2c75eed | ||
| + | 1402d3edfd8d64019b35eac50ab04f0239080a879f000b42253688df27967c492e721c9e91407edcf9ebd01fd7a17bc0219784322b | ||
| + | 5f0b42253688df27967c492e721c9e91402b5bebae08f2851e97e139390d4d6245925a96bbca45277ebecfd06fa54b510edb4ec98a | ||
| + | 7538f2c75eed1402d3edfd8d7edcf9ebd01fd7a17bc0219784322b5f3454fe7467cd0e2b6036f48a3c2246930b42253688df27967c | ||
| + | 492e721c9e91403856820345c0e11691b05d22b6005906668020a4b98905a562e051955ea720177edcf9ebd01fd7a17bc021978432 | ||
| + | 2b5fec0e366b9ea7d725dc81fdec29b57bb3 | ||
| + | |||
| + | Napomena: u ciphertextu nema znakova novog reda, ali su ovdje dodani radi lakše čitljivosti. | ||
| + | |||
| + | telnet chal.platforma.hacknite.hr 8083 | ||
| + | netcat chal.platforma.hacknite.hr 8083 | ||
| + | |||
| + | Flag je u formatu CTF2022[brojevi] | ||
| - | Flag je u formatu CTF2021[brojevi] | ||
| </ | </ | ||
| - | U prilogu se još nalazi i program | + | U prilogu se nalazi i datoteka encrypt.py. |
| - | Možemo pokušati XOR-ati cijeli tekst za šifriranje s null-byteovima | + | |
| - | < | + | Pokušajmo se spojiti na chal.platforma.hacknite.hr i port 8083. Imamo mogućnost pisanja, a kao rezultat dobijemo ispis kodiranog teksta |
| - | python3 -c "print(' | + | |
| + | {{ :nc-a.jpg?600 |}} | ||
| + | |||
| + | Vidimo da se svaka pojava istog znaka šifrira jednako, što i odgovara AES ECB modu. Sad upišimo dio flaga koji znamo, | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | Vidimo da počne odmah na početku. Sad nam preostaje dešifrirati ostatak | ||
| + | |||
| + | < | ||
| + | data = "CTF2022[" | ||
| + | import subprocess | ||
| + | def get_enc(i): | ||
| + | return str(subprocess.check_output(f" | ||
| + | | ||
| + | |||
| + | cipher = open(" | ||
| + | |||
| + | while data[-1] != " | ||
| + | # | ||
| + | for x in " | ||
| + | #print(data + x) | ||
| + | r = get_enc(data + x) | ||
| + | if cipher.startswith(r): | ||
| + | data += x | ||
| + | break | ||
| + | print(data) | ||
| </ | </ | ||
| - | Nakon što smo dobili ključ, XOR-amo ga s tekstom | + | |
| + | Objasnimo | ||
| + | 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 | ||
| + | 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 | ||
| + | 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, | ||
| + | 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 | ||
| + | |||
| + | 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.1700474832.txt.gz · Last modified: 2025/12/01 11:40 (external edit)