Przeskocz do treści

Delta mi!

A jednak się da!

O kryptografii klucza publicznego i podpisie cyfrowym (AJSD I)

Tomasz Kazana

o artykule ...

  • Publikacja w Delcie: październik 2018
  • Publikacja elektroniczna: 1 października 2018
  • Autor: Tomasz Kazana
    Afiliacja: Instytut Informatyki, Uniwersytet Warszawski
  • Wersja do druku [application/pdf]: (112 KB)

Problem szyfrowania przesyłanych wiadomości sięga jeszcze czasów starożytnych, więc naszego nowego deltowego cyklu artykułów o kryptologii prezentowanego w rubryce "A jednak się da!" nie możemy nie zacząć od przypomnienia najstarszego znanego systemu szyfrowania, mianowicie szyfru Cezara. Szyfr ten nie jest specjalnie wyrafinowany...

Po prostu umawiamy się, że (na przykład) zamiast litery A będziemy pisać G; zamiast B - literę H; zamiast C - literę I i tak dalej, to znaczy: zamiast n-tej litery alfabetu będziemy pisać (n + 6) -tą literę. (Tak naprawdę (((n + 5)mod 26)+ 1) -tą literę, gdyż pod koniec musimy alfabet cyklicznie zawinąć do początku.) Równie dobrze moglibyśmy alfabet przesuwać nie o 6 pozycji, a o 3 pozycje, o 17 pozycji, czy ogólnie: o |KCezar pozycji.

Nieco bardziej skomplikowany jest szyfr permutacyjny. Tutaj dwie strony ustalają zawczasu permutację literek

Kperm {A,

a następnie - aby zaszyfrować tekst - przykładają tę permutację do kolejnych literek wiadomości, uzyskując szyfrogram, czyli tekst zaszyfrowany. Odszyfrowanie wygląda podobnie, tylko przykładamy kolejno permutację odwrotną do Kperm.

Oba powyższe przykłady wpisują się w pewien bardzo ogólny schemat szyfrowania. Mianowicie, na początku, jeszcze przed jakimkolwiek szyfrowaniem, dwie strony (ochrzcijmy je imionami Aldona i Bogumił) muszą się spotkać i ustalić coś sekretnego, czyli tak zwany klucz kryptograficzny K, | w naszym przykładach, odpowiednio: K | Cezar oraz K . perm Następnie, gdy Aldona chce przekazać Bogumiłowi wiadomość |m, musi ona najpierw obliczyć wartość |c = Enc(K, m) (gdzie Enc jest specyficznym opisem wybranego szyfru) i wysłać właśnie ją do Bogumiła. Bogumił otrzymawszy szyfrogram |c, dokonuje obliczenia |m gdzie Dec oznacza funkcję deszyfrującą. Oczywiście, żeby wszystko miało ręce i nogi, musi zawsze (dla każdego wyboru |K ) zachodzić m | oraz - ze względów bezpieczeństwa - podsłuchanie szyfrogramu |c przez niecną Helgę nie może ujawnić właściwego komunikatu, czyli |m. Ten ostatni wymóg nie jest wcale banalny do sformalizowania, ale my pozostaniemy przy nieformalnym określeniu - chcemy po prostu, aby dla Helgi było bardzo trudno wywnioskować cokolwiek na temat |m z wartości |c. Dodatkowo w środowisku kryptologicznym przyjmuje się, że Helga zawsze wie, jakiego systemu używają Aldona z Bogumiłem - innymi słowy zna definicję |Enc, a jedyne czego nie zna, to klucz K (to założenie to treść tak zwanej zasady Kerckhoffsa). Więcej o samej zasadzie Kerckhoffsa oraz motywacji jej przyjęcia pisaliśmy w Migawce w Delcie 07/2018

Przez setki lat rozwój kryptologii przebiegał dokładnie według powyższego schematu. Wymyślano przeróżne szyfry, po czym próbowano się upewnić, czy aby na pewno znajomość Enc(K, m) (oraz definicji Enc ) nic nie mówi o |m. Okazało się dość szybko, że zarówno szyfr Cezara, jak i permutacyjny, nie są bezpiecznymi szyframi, ale za to inne współczesne szyfry, np. AES czy Triple-DES, uchodzą za bezpieczne i są stosowane powszechnie do dziś.

Wszystko pięknie, ale widać, gdzie znajduje się spora niewygoda. Żeby szyfrować, trzeba bezpiecznie ustalić wspólny tajny klucz. Zadanie to wcale nie wydaje się banalne (szczególnie, gdy Aldona i Bogumił mieszkają na różnych kontynentach, trwa wojna etc.), więc można by sformułować następujące naiwne marzycielskie pytanie:

Czy da się skonstruować szyfr taki, który nie wymaga ustalania wspólnego tajnego klucza, to znaczy, aby po prostu c | = Enc(m)?

Łatwo wykazać, że postulat powyższy nie jest możliwy do zrealizowania.

Dowód. Załóżmy przeciwnie, a więc, że takie Enc | istnieje. Wówczas:

(1)
Oczywiście Bogumił musi być w stanie deszyfrować przychodzące do niego szyfrogramy, a więc:
(2)
Istnieje taka funkcja Dec, że |Dec(Enc(m)) ; oznacza to, że:
(3)
Dec jest funkcją odwrotną do |Enc ; pamiętajmy, że:
(4)
Helga zna definicję Enc (zasada Kerckhoffsa).
(5)
Wystarczy więc, że Helga obliczy funkcję odwrotną do (znanej jej!) funkcji |Enc i już jest w stanie robić to, co Bogumił, czyli deszyfrować.
(6)
Niestety, oznacza to, że szyfrowanie Enc nie jest bezpieczne, co kończy dowód.

obrazek

Pomimo znajomości powyższego rozumowania w roku 1976 dwóch dżentelmenów - Whitfield Diffie oraz Martin Hellman - postanowiło (w pracy New Directions in Cryptography) bezczelnie zapytać: a może jednak się da? Więcej, już rok później panowie Ron Rivest, Adi Shamir oraz Leonard Adleman (korzystając ze wskazówek z pracy D-H) wykazali, że faktycznie: da się! Czytelnik Logiczny powinien w tym momencie poczuć co najmniej niesmak. Akapit wyżej pokazaliśmy dowód, że czegoś się nie da, a dalej coś tam jeszcze dywagujemy? Haczyk - jak zwykle w matematyce - tkwi w założeniach. Diffie i Hellman nie wykazali, że powyższy dowód jest błędny. Zaproponowali tylko pewne dodatkowe założenie, przy którym ten dowód przestaje być poprawny! Konkretnie chodzi o punkt 5. tego dowodu. Jeśli założymy (jak proponują D-H), że Helga ma ograniczoną moc obliczeniową, to wcale nie jest jasne, że będzie potrafiła szybko odwrócić znaną sobie funkcję Enc. Tym tropem poszli Rivest, Shamir i Adleman, proponując swój szyfr, znany dziś jako szyfrowanie RSA.

Zanim przejdziemy do szczegółów, spróbujmy naświetlić samą esencję pomysłu. Idea opiera się na spostrzeżeniu, że (generalnie) mnożenie jest szybkie, ale już jego odwracanie (czyli rozkład na czynniki pierwsze) - bardzo trudne. Innymi słowy, chodzi o znalezienie takich funkcji |Enc oraz Dec, aby do wyliczania |Enc wystarczała znajomość |p⋅q, ale już do szybkiego obliczania Dec - konieczne były zarówno p, jak i q. Wówczas Bogumił może wszystkim (i Aldonie, i Heldze, i Kamili, i Markowi, i Szymonowi i każdemu, kto tylko będzie chciał) bez skrępowania ujawniać opis |Enc, ALE zachowując dla siebie czynniki p oraz |q (czyli w istocie opis Dec ). Naprawdę jest to troszkę bardziej skomplikowane i wygląda tak.

Rzeczywiście Bogumił wybiera dwie duże (rzędu setek cyfr) liczby pierwsze p i |q oraz oblicza ich iloczyn n = p⋅q. Następnie oblicza |ϕ(n) = (p− 1)⋅(q − 1) oraz losuje dowolną liczbę e względnie pierwszą z |ϕ(n). Teraz znajduje taką liczbę d, że

e ⋅d = 1mod ϕ (n). (*)

Okazuje się, że powyższa operacja (wyznaczenie d) da się wykonać bardzo szybko (np. za pomocą rozszerzonego algorytmu Euklidesa), gdy znamy |p,q oraz e, natomiast wierzymy, że jest bardzo trudna, gdy znamy tylko | n oraz | e. Pozostaje opisać funkcję szyfrującą i deszyfrującą |(m, :

pict

Aby uznać szyfrowanie RSA za poprawne i bezpieczne, należy sprawdzić, że:

(a)
Dec(Enc(m)) czyli, że |m Dowód tego faktu pominiemy, pozostawiając tylko uwagę, że - korzystając z kilku faktów z teorii liczb - da się go wyprowadzić wprost z równania (*).
(b)
Znajomość opisu Enc (czyli liczb n i e) nie pomoże odtworzyć funkcji Dec, gdyż - jak już wspomnieliśmy - wierzymy, że z |n i e nie da się łatwo obliczyć d, które jest niezbędnym elementem opisu Dec.

Jak to wygląda w praktyce?

Szyfrowanie RSA jest niezwykle popularne i wygodne. Aby z niego korzystać, należy postąpić dokładnie tak, jak Bogumił w opisie wyżej. Następnie parę |(n,e) (tak zwany klucz publiczny) należy rozgłaszać wszem i wobec, ponieważ jej znajomość umożliwia światu bezpieczne wysyłanie komunikatów przeznaczonych tylko dla nas. Z drugiej strony - liczbę d (osobisty klucz prywatny) oraz rozkład |p i q należy trzymać w wielkiej tajemnicy i nigdy nikomu nie zdradzać.

Jaki to ma związek z podpisem cyfrowym?

Podpis cyfrowy Bogumiła to taka para funkcji (Sign, Check), że:

  • tylko Bogumił potrafi obliczać wartości s = Sign(m) (czyli podpisywać m );
  • każdy potrafi obliczać wartości Check(m, | (czyli sprawdzać autentyczność podpisu s pod dokumentem |m );
  • funkcja Check zachowuje się dobrze, to znaczy Check(m, oraz Check(m, jeśli tylko x ≠ Sign(m).

Powyższa definicja wydaje się zupełnie intuicyjna i nie wymaga szerszego komentarza. Wyzwaniem jest jednak znaleźć odpowiednie Sign | oraz |Check. Okazuje się, że znajomość RSA bardzo nam pomoże. Przyjmijmy bowiem:

pict

gdzie n, e oraz |d są takie same jak w RSA (w szczególności: |n i e są publiczne, a d - znane tylko Bogumiłowi).

Innymi słowy: podpis Sign zachowuje się jak Dec, a weryfikacja podpisu |s dokumentu m sprowadza się do sprawdzenia, czy Enc(s) | = m.

Teraz widać, że bezpieczeństwo takiego podpisu jest takie samo, jak bezpieczeństwo RSA. Jeśli bowiem (w RSA) tylko Bogumił mógł deszyfrować, to u nas tylko on może podpisywać. Skoro wcześniej każdy mógł szyfrować ( Enc jest publiczna), to teraz każdy może obliczać funkcję Check. Wreszcie - funkcja |Check zachowuje się zgodnie z oczekiwaniami, co wynika wprost z faktu, że |Dec jest odwrotna do |Enc.

Postscriptum

Na zakończenie jeszcze mała obserwacja, która na razie pewnie wyda się mało użyteczna (choć zaryzykujemy stwierdzenie, że jest elegancka i zaskakująca), ale będziemy jej potrzebować w kolejnych częściach cyklu A jednak się da. Otóż chcemy zdefiniować protokół tak zwanego ślepego podpisu. To znaczy: chcielibyśmy, aby Bogumił mógł (jeśli tylko ma taką fantazję) pozwolić Aldonie na podpisanie czegoś, czego sam nigdy nie zobaczy na oczy. Możemy zrobić to tak:

1.
Aldona wybiera dokument do podpisu |m oraz losową liczbę |x ∈{1,2,...,n} ;
2.
Aldona wysyła do Bogumiła liczbę c = m ;
3.
Bogumił oblicza a = cd mod n i odsyła wynik Aldonie;
4.
Aldona oblicza s = a/x mod n.

Jako ćwiczenie pozostawiamy sprawdzenie, że w protokole powyżej: (1) Bogumił nie jest w stanie odtworzyć dokumentu m oraz (2) liczba s | jest poprawnym podpisem Bogumiła pod dokumentem |m.