Cryptopals zestaw 2 ćwiczenie 15

przez | 28 lipca 2020

W tym zadaniu wielki powrót padding (ale chyba największy nadal przed nami). Tym razem musimy stworzyć funkcję, która na wejściu dostaje dane, które powinny być wyrównane do wielokrotności długości bloku i musi sprawdzić czy są one prawidłowo wyrównane. Jeżeli wszystko jest w porządku to usuwamy padding i zwracamy tylko użyteczne dane, jeżeli coś jest nie tak z paddingiem to funkcja wyrzuca wyjątek.

Poprzednim razem kiedy opisywałem padding dodawałem link bodajże do Wikipedii, tym razem bardzo dobry opis od IBM: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.csfb400/pkcspad.htm . Znamy zasadę zgodnie z którą obliczane są wartości bajtów tworzących padding, więc nie ma sensu za bardzo się nad tym rozpisywać, wypiszę tylko warunki które spowodują, że nasza funkcja rzuci wyjątek:

  1. Długość danych nie jest wielokrotnością długości pojedynczego bloku. Np. długość bloku wynosi 16 bajtów a funkcja dostała 34 baty danych.
  2. Wartość bajtów tworzących padding jest większa niż długość bloku.
  3. Wartość bajtów tworzących padding jest równa długości danych. To taki warunek brzegowy. Normalnie kiedy dane użytkownika są wielokrotnością bloku dodawany jest dodatkowy blok wypełniony tylko bajtami tworzącymi padding. Jeżeli zdarzy się to w przypadku kiedy nasza funkcja otrzyma tylko jeden blok, oznaczało by to, że nie ma tam danych użytkownika a jedynie sam padding. Ja w swojej implementacji uznaję to za błędne dane.
  4. Wartość/długość paddingu wynosi 0.
  5. Którykolwiek z bajtów tworzących padding ma inną wartość niż pozostałe bajty.

Jeżeli żaden z powyższych warunków nie jest spełniony to znaczy, że dane są prawidłowe i możemy usunąć ostatnich N bajtów i zwrócić same dane użytkownika. Wartość N czyli długość padding i jednocześnie wartość bajtów z których się składa poznajemy sprawdzając ostatni bajt danych otrzymanych od użytkownika. Moja implementacja:

def stripPKCS7(input_data, block_size):
    data_len = len(input_data) 
    if (data_len%block_size) != 0:
        raise Exception('Invalid padding.')
    
    pad_len = input_data[-1]
    if (pad_len > block_size) or (pad_len == data_len) or (pad_len == 0):
        raise Exception('Invalid padding.')
    
    for idx in range(2, pad_len+1):
        if (input_data[-idx] != pad_len):
            raise Exception('Invalid padding.')
    return input_data[:-pad_len]

Kod testowy:

def s2challenge15():
    print("Challenge 15 start")
    test_string1 = (b"ICE ICE BABY\x04\x04\x04\x04")
    test_string2 = (b"ICE ICE BABY\x05\x05\x05\x05")
    test_string3 = (b"ICE ICE BABYABCD\x10\x10\x10\x10\x10"
                    b"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10")
    test_strings = [test_string1, test_string2, test_string3]
    
    for test_string in test_strings:
        try:
            test_string = stripPKCS7(test_string, 16)
        except:
            print("Test string ", test_string," has invalid padding.")
        else:
            print("Stripped data1: ", test_string)

Całość tradycyjnie do znalezienia tutaj: https://gitlab.com/akoltys/cryptopals.

Dodaj komentarz

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