Cryptopals zestaw 2 ćwiczenie 9

przez | 3 czerwca 2020

Pierwsze ćwiczenie z nowego zestawu, aż chce się powiedzieć – lekkie, łatwe i przyjemne. I tak właśnie jest. Chodzi o dopełnianie danych, które mają zostać zaszyfrowane, żeby ich długość była wielokrotnością długości bloku używanego przez algorytm szyfrujący np. w przypadku AES jest to 16 bajtów.

Jest to istotny problem ponieważ nie można oczekiwać od użytkownika, że będzie dbał, aby dane miały długość będącą wielokrotnością jakiejś wartości. Większość użytkowników nawet nie będzie miała pojęcia, że dane są rozbijane na bloki, ani tym bardziej jaka jest długość tych bloków. Mamy dane i chcemy je zaszyfrować, cała reszta nas nie obchodzi.

To w jaki sposób wygenerujemy „wypełniacz” nie jest bez znaczenia. Bo teoretycznie moglibyśmy dodawać na końcu same 0xFF albo 0x00, ale co jeśli ostatni bajt ma mieć wartość 0x00 lub 0xFF? Są różne sposoby, żeby poradzić sobie z tym problemem (można sobie o tym poczytać chociażby na Wikipedii: https://en.wikipedia.org/wiki/Padding_(cryptography)), naszym zadaniem jest implementacja algorytmu, który zrobi padding PKCS#7. To wyrównywanie długości danych po angielsku nazywane jest padding i dla wygody też będę używał tej nazwy.

Założenie według którego działa PKCS#7 jest bardzo proste: jeżeli do wyrównania brakuje nam 3 bajtów to „zapychaczem” będzie ciąg bajtów każdy o wartości 3, jeżeli brakuje nam 5 bajtów będzie to ciąg bajtów o wartościach 5.
Przykładowo: dane od użytkownika mają długość 6 batów a docelowo mają mieć długość 8 bajtów.
0xAA 0xBB 0xCC 0xDD 0xEE 0xFF
Po dodaniu paddingu:
0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0x22 0x22

Jest dodatkowa reguła na wypadek gdyby dane od użytkownika mały jednak długość będącą wielokrotnością długości bloku danych, wtedy dodawany jest dodatkowy blok wypełniony bajtami o wartościach równych długości bloku danych.
Przykładowo: dane od użytkownika mają długość 8 bajtów i docleowo mają mieć właśnie taką długość.
0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF
Po dodaniu paddingu:
0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0x08 0x08 0x08 0x08 0x08 0x08 0x08 0x08

Sam algorytm jest bardzo prosty w implementacji:

def addPaddingPKCS7(input_data, block_len):
    if isinstance(input_data, str):
        input_data = bytearray(input_data, 'ascii')
        
    padding_value = (block_len - (len(input_data)%block_len))
    padding = []
    if padding_value > 0:
        padding = [padding_value] * padding_value
    return input_data + bytearray(padding)

Pierwszy „if” można zignorować ponieważ został dodany po to, żeby w kolejnych zadaniach można było w wygodny sposób korzystać z tej funkcji. Najpierw wyliczana jest wartość bajtów z których będzie składał się nasz padding – od długości bloku danych podanej w zmiennej block_len odejmujemy resztę z dzielenia długości danych przez długość bloku danych. Następnie tworzymy padding o długości i wartości równej wyliczonej wcześniej wartości. Nie musimy wykrywać czy blok jest wielokrotnością ponieważ, wyliczona w tym wypadku wartość padding_value będzie równa block_len.

Dodaj komentarz

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