Rozdział 6 Pakowanie plecaka 6.1 Postawienie problemu Jak zauważyliśmy, szyfry oparte na rachunku macierzowym nie są przerażająco trudne do złamania. Zdecydowanie trudniejszy jest kryptosystem oparty na następującym problemie pakowania plecaka: Załóżmy, że musimy zabrać ze sobą na wycieczkę w góry wiele,,potrzebnych przedmiotów. Jednakże do dyspozycji mamy jedynie plecak o ograniczonej pojemności S. Przedmioty mają objętości a 1, a 2,..., a n, które po zsumowaniu dają objętość większą od S. Musimy zatem z czegoś zrezygnować. Jedynym kryterium jest tu tylko to, by plecak był zapakowany optymalnie, tj. bierzemy tylko te przedmioty, których objętości dają sumę S. Co zatem włożyć do plecaka? 6.1.Przykład. Niech (a 1, a 2, a 3, a 4, a 5 ) = (2, 7, 8, 11, 12) oraz niech S = 21. Wówczas mamy a 1 + a 3 + a 5 = S oraz a 1 + a 2 + a 5 = S. Zatem zabieramy ze sobą przedmioty pierwszy, trzeci i piąty, lub pierwszy, drugi i szósty. Powyższy problem można sformułować następująco: Dla danych liczb naturalnych a 1, a 2,..., a n oraz S, znaleźć taki ciąg x 1, x 2,..., x n złożony z zer i jedynek, żeby zachodziła równość a 1 x 1 + a 2 x 2 + + a n x n = S. (6.2) Rozważając ciąg z przykładu 6.1 dostajemy dwa rozwiązania: x 1 = x 3 = x 4 = 1, x 2 = x 3 = 0 oraz 1 x 1 = x 2 = x 5 = 1, x 3 = x 4 = 0.
Aby sprawdzić, czy (6.2) zachodzi musimy wykonać co najwyżej n dodawań, jednak żeby rozwiązać problem pakowania plecaka metodą prób i błędów, musimy sprawdzić wszystkie 2 n możliwości. Oznacza to, że rozwiązanie powyższego problemu zajmuje O(2 n ) czasu. Najszybszy znany algorytm działa w czasie O(2 n 2 ). Jeśli n = 100, to komputer wykonujący 2 20 operacji na sekundę potrzebuje na rozwiązanie problemu pakowania plecaka czas rzędu 2 30, czyli około miliard sekund albo ponad 30 lat! Pewne wartości liczb a 1, a 2,..., a n zdecydowanie przyśpieszają rozwiązanie problemu pakowania plecaka. Na przykład, jeśli są to potęgi dwójki, to rozwiązanie sprowadza się do znalezienia rozwinięcia liczby S w systemie dwójkowym. Rozwinięcie to znajdujemy w czasie logarytmicznym stosując tzw.,,chciwy algorytm, który opiszemy poniżej. 6.2 Szybko rosnące ciągi Ciąg liczb naturalnych a 1, a 2,..., a n nazywamy szybko rosnącym, jeśli j 1 a i < a j dla j {2, 3,..., n}. Przykładem szybko rosnącego ciągu jest 2,3,7,14,27. Niech S = 37. Wówczas,,chciwy algorytm działa następująco: Zawsze bierzemy największy przedmiot jaki się mieści. Tak więc x 5 = 1, ale x 4 = 0 ponieważ 27 + 14 > 37. x 3 = 1 gdyż 27 + 7 < 37. Podobnie, x 2 = 1 oraz x 1 = 0. Ogólnie, jeśli mamy szybko rosnący ciąg a 1, a 2,..., a n, to wyznaczamy x n, x n 1,..., x 1 korzystając ze wzorów { 1, jeśli S a n x n = 0, jeśli S < a n oraz x j = { 1, jeśli S n i=j+1 x ia i a j 0, jeśli S n i=j+1 x ia i < a j dla j n 1, n 2,..., 1. Problem pakowania plecaka dla ciągów szybko rosnących może być więc rozwiązany bardzo szybko. Poniższy system kryptograficzny Merklego Hellmana, który do roku 1982 był uważany za najlepszy system o tzw. kluczu publicznym opiera się na,,zamianie problemu trudnego na problem łatwy. 2
6.3 Kryptosystem oparty na problemie pakowania plecaka Załóżmy, że a 1, a 2,..., a n jest szybko rosnącym ciągiem liczb naturalnych. Niech m będzie liczbą naturalną większą od 2a n. Weźmy dowolną liczbę całkowitą nieujemną w względnie pierwszą z m i utwórzmy ciąg b 1, b 2,..., b n biorąc wa 1, wa 2,..., wa n modulo m. Jeżeli b 1, b 2,..., b n nie jest ciągiem szybko rosnącym, to żeby rozwiązać problem pakowania plecaka n x ib i = S, nie możemy użyć chciwego algorytmu. Jednakże, jeśli znamy w 1, to możemy rozwiązać problem pakowania plecaka x i a i = S 0, (6.3) gdzie S 0 Sw 1 (mod m). Kiedy mamy już rozwiązany problem (6.3), to wiemy, że w 1 S = w 1 x i b i x i a i (mod m). (6.4) Powyższą procedurę opiszemy na przykładzie. 6.5.Przykład. Rozważmy szybko rosnący ciąg (a 1, a 2, a 3, a 4, a 5 ) = (3, 5, 9, 20, 44), m = 89 oraz w = 67. Zauważmy, że w 1 = 4. Wówczas (b 1, b 2, b 3, b 4, b 5 ) = (23, 68, 69, 5, 11). Żeby rozwiązać problem pakowania plecaka 23x 1 + 68x 2 + 69x 3 + 5x 4 + 11x 5 = 84, mnożymy obie strony powyższego równania przez 4 i redukujemy modulo 89 otrzymując 3x 1 + 5x 2 + 9x 3 + 20x 4 + 44x 5 = 69. Teraz rozwiązujemy łatwo powyższy problem pakowania plecaka otrzymując x 1 = x 3 = 0; x 2 = x 4 = x 5 = 1. Zatem nasz pierwotny problem ma rozwiązanie 68 + 5 + 11 = 84. System kryptograficzny oparty na problemie pakowania plecaka działa następująco. Wybieramy szybko rosnący ciąg a 1, a 2,..., a n, liczbę m > 2a N oraz liczbę w względnie pierwszą z N. Następnie obliczamy wyrazy ciągu b 1, 3
b 2,..., b N i podajemy je do publicznej wiadomości. Jeśli ktoś chce przesłać do nas wiadomość, najpierw koduje ją za pomocą zer i jedynek (na przykład jak w poniższej tabelce), a następnie dzieli otrzymany ciąg na bloki długości N. Dla każdego bloku x 1, x 2,..., x N, nadawca oblicza sumę N x ib i i otrzymany ciąg sum wysyła jako tekst zaszyfrowany. litera odpowiednik litera odpowiednik A 00000 N 01101 B 00001 O 01110 C 00010 P 01111 D 00011 Q 10000 E 00100 R 10001 F 00101 S 10010 G 00110 T 10011 H 00111 U 10100 I 01000 V 10101 J 01001 W 10110 K 01010 X 10111 L 01011 Y 11000 M 01100 Z 11001 Dla przykładu zaszyfrujemy wiadomość REPLY IMMEDIATELY używając ciągu C = (2002, 3337, 2503, 2170, 503, 172, 3347, 855, 709, 417). Najpierw zamieniamy litery (a w zasadzie digramy) na bloki 10 cyfrowe: 1000100100 0111101011 1100001000 0110001100 0010000011 0100000000 1001100100 0101111000 Następnie obliczamy odpowiednie sumy wyrazów ciągu C otrzymując kryptogram (3360, 12986, 8686, 10042, 3629, 3337, 5530, 9729). (6.6) Na przykład dodajemy 2002, 503 i 855 żeby otrzymać 3360. Zauważmy teraz, dlaczego klucz szyfrujący może być podany do publicznej wiadomości: Mamy tekst jawny oraz kryptogram właśnie otrzymany, 4
ale czy jesteśmy w stanie odczytać inny kryptogram, np. (4619, 3337), zaszyfrowany tym samym kluczem? Powyższa idea prowadzi do powstania sieci korespondentów. Każdy użytkownik sieci ma swój prywatny klucz rozszyfrowujący, a klucze szyfrujące mogą być umieszczone w swoistej,,książce telefonicznej, która jest dostarczona każdemu użytkownikowi sieci. Ideę tę omówimy w następnym rozdziale, a teraz pokażemy jak można łatwo rozszyfrować szyfr (6.6). Do rozszyfrowania potrzebujemy oryginalnego ciągu szybko rosnącego, jakim jest (2, 11, 14, 29, 58, 119, 241, 480, 959, 1917), liczby m = 3837 oraz w 1 = 23. Żeby rozszyfrować 3360, znajdujemy najpierw 3360 23 540 (mod 3837) i zauważamy, że 540 = 480 + 58 + 2. Zatem odpowiadającym blokiem zero jedynkowym jest 1000100100, który odpowiada digramowi RE. Zauważmy, że jeżeli długość ciągu jest równa 5, to opisany szyfr jest bardziej skomplikowaną wersją klasycznego szyfru permutacyjnego - litera alfabetu jest zastąpiona liczbą. W opisanym przykładzie liczbą zastępujemy digram tekstu jawnego. Aby odróżnić szyfr oparty na problemie pakowania plecaka od szyfru klasycznego powinniśmy wybierać ciągi długości różnej niż wielokrotność długości bloku reprezentującego litery alfabetu. W roku 1983 Shamir opublikował pracę, która zdyskwalifikowała system kryptograficzny oparty na problemie pakowania plecaka jako system bezpieczny. Otóż okazało się, że szyfr ten można złamać w czasie wielomianowym. Po roku 1983 starano się utrudnić szyfr, ale ponieważ każda próba kończyła się szybko podobną publikacją, szyfry oparte na problemie pakowania plecaka nie mają dziś dużego powodzenia, mimo że niektóre z nich w dalszym ciągu są nie złamane. 5