AES

AES (Advanced Encryption Standard), poznat i pod svojim originalnim nazivom Rijndael, sustav je simetrične kriptografije temeljen na supstitucijsko-permutacijskim poljima.
 Shema supstitucijsko-permutacijskog polja AES koristi fiksnu veličinu bloka od 128 bitova te veličinu ključa od 128, 192 ili 256 bitova. Provodi se nad matricom 4×4, 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 enkripcijski postupak

Funkcije koje AES koristi matematički su opisane u nastavku:
1) Zamjena znakova

znak = Sbox[znak] 

2) Dodaj potključ

blok = blok ⊕ potključ[i]

3) Posmakni redove
Rotira (kružno posmiče) znakove ulijevo u svim retcima osim prvog za unaprijed poznati broj mjesta koji je ovisan o N.

4) Pomiješaj stupac bloka
Množi se stupac po stupac bloka s fiksnim polinomom:

a(x) = 03Hx3 + 01Hx2 + 01Hx + 02H mod x4+1 

Odnosno, za svaki stupac bloka računa se stupac novog stanja:

Postoje razni načini AES kriptiranja koji određuju kako se ulazni podatci dijele u blokove, kako se blokovi kriptiraju i kombiniraju, kako enkripcija upravlja problemima kao što su integritet podataka ili inicijalizacijski vektori (IV) i slično.

Često korišteni AES načini kriptiranja su:
1) ECB (Electronic Codebook)

 ECB shema

2) CBC (Cipher Block Chaining)

 CBC shema

3) CFB (Cipher Feedback) i OFB (Output Feedback)

 CFB/OFB shema

4) CTR (Counter Mode)

 CTR shema

5) GCM (Galois/Counter Mode)

 GCM shema

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 - AES kriptirana poruka

Ivan je na faksu učio o modernim kriptografskim algoritmima. Toliko je očaran AES algoritmom da je odlučio
samostalno napraviti program za šifriranje svojih najtajnijih informacija. Pokušaj dešifrirati ciphertext
kako bi provjerio je li Ivanov program zaista siguran.

ciphertext (u zasebnoj datoteci):
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]

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:

Vidimo da se svaka pojava istog znaka šifrira jednako, što i odgovara AES ECB modu. Sad upišimo dio flaga koji znamo, a zatim i cijeli ciphertext da vidimo gdje u njemu počinje flag:

Vidimo da počne odmah na početku. Sad nam preostaje dešifrirati ostatak teksta da bismo dobili flag. Napišimo jednostavnu Python skriptu za to:

data = "CTF2022["
import subprocess
def get_enc(i):
    return str(subprocess.check_output(f"echo \"{i}\" | nc chal.platforma.hacknite.hr 8083",
     shell=True))[2:-3]
 
cipher = open("ciphertext", "r").read()
 
while data[-1] != "]":
    #print(data)
    for x in "123456789[]":
        #print(data + x)
        r = get_enc(data + x)
        if cipher.startswith(r):
            data += x
            break
print(data)

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 se poslužitelj ne bi preopteretio prevelikim brojem zahtjeva.

Izvori

[1] Christof Paar, Jan Pelzl, Understanding Cryptography, Springer-Verlag Berlin Heidelberg, 2009.
[2] https://platforma.hacknite.hr/challenges
[3] Kriptografija i kriptoanaliza, predavanja, FER
[4] Budin, L.; Golub, M; Jakobović, D., Jelenković, L (2010.) (2013.), Operacijski sustavi, Element, Zagreb
[5] https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf