Cryptopals zestaw 2 ćwiczenie 11

przez | 30 czerwca 2020

Kolejny raz będziemy opierali się na właściwości trybu ECB – powtarzające się bloki w danych wejściowych powoduje powstanie powtarzających się bloków w danych wyjściowych. Nasze zadanie jest podzielone na kilka etapów.

W pierwszym kroku musimy stworzyć funkcję która generuje 16-bajtowy ciąg bajtów którego będziemy używali jako klucza szyfrującego. Ja stworzyłem funkcję która przyjmuje jako parametr długość losowych danych które mają zostać wygenerowane – to nam się przyda w dalszej części zadania.

def generateRandomData(data_size):
    result = []
    for i in range(0, data_size):
        result.append(randint(0, 255))
    return bytearray(result)

W kolejnym kroku mamy stworzyć funkcję, która będzie szyfrowała podane jako parametr dane losowym kluczem.

def encryptionOracle(input_data):
    if isinstance(input_data, str):
        input_data = bytearray(input_data, 'ascii')
    input_data = generateRandomDataSize(5, 10) + input_data + generateRandomDataSize(5, 10)
    iv_data = generateRandomData(16)
    key_data = generateRandomData(16)
    ciph = CustomAES()
    ciph_mode = CustomAES.Mode.CBC
    if randint(0, 1) == 0:
        ciph_mode = CustomAES.Mode.ECB
    else:
        ciph_mode = CustomAES.Mode.CBC
    return ciph.encode(input_data, key_data, ciph_mode, iv_data), ciph_mode

Funkcja ma robić kilka rzeczy:
1. Dane mają być szyfrowane w trybie ECB lub CBC – to jakim tryb będzie użyty jest losowe (50% ECB i 50% CBC).
2. Do podanych przez użytkownika danych na początku i na końcu dodawane są dodatkowe losowej długości (5-10 bajtów) bloki losowych bajtów.
3. Jeżeli dane będą szyfrowane w trybie CBC ma być użyty losowy IV.
Dodatkowo na potrzeby testów moja funkcja zwraca informację o tym jaki tryb był użyty w danym wywołaniu w celu ułatwienia weryfikacji poprawności algorytmu wykrywającego użyty tryb.

def s2challenge11():
    print("Challenge 11 start")
    for i in range(0, 10):
        ciphered_data, cipher_type = oracles.encryptionOracle("a"*48)
        print(i+1, ". Cipher type: ", cipher_type == CustomAES.Mode.ECB, " Guessed Type", canBeAesECB(ciphered_data))

Jak widać to zadanie nie jest zbyt skomplikowane. Do wcześniej stworzonej funkcji jako parametr przekazuję ciąg 48 znaków „a”. Dlaczego 48 znaków? Ponieważ wiemy, że AES tworzy bloki o długości 16 bajtów, ale nie wiemy jakiej długości dane będą dodane na początku ciągu który kontrolujemy, to żeby mieć pewność, że wśród zwróconych bajtów będą co najmniej dwa bloki o takich samych wartościach w przypadku kiedy użyty będzie tryb ECB. Blok mógłby być krótszy bo wiemy, że dane na początku mają długość między 5 a 10 bajtów: w przypadku kiedy wylosowana długość to 5 bajtów będziemy potrzebowali 13 na dopełnienie pierwszego bloku a następnie dwa bloki po 16 bajtów, więc minimalna długość jaka możemy przekazać to 45. Używając długości 48 mamy pewność, że algorytm zadziała niezależnie od danych na które nie mamy wpływu.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *