Algebraiczne aspekty kodowania i kryptografii, 2
Transkrypt
Algebraiczne aspekty kodowania i kryptografii, 2
Algebraiczne aspekty kodowania i kryptografii, 2 1 Kody cykliczne Zdefiniujmy funkcję shr : {0, 1}m → {0, 1}m shr(a0 a1 . . . am−2 am−1 ) = am−1 a0 a1 . . . am−2 . Kod K ⊆ {0, 1}m spełnia warunek cykliczności, jeżeli dla każdego ~a ∈ K mamy shr(~a) ∈ K. Kod liniowy spełniający warunek cykliczności nazywamy cyklicznym. 1.1 Szeregi formalne i wielomiany Kody cykliczne dobrze opisuje się za pomocą wielomianów, rozumianych jako wielomiany formalne, a więc jako szczególne szeregi formalne. Dla ciała F przyjmujemy, że F [[x]] oznacza zbiór formalnych szeregów nad ciałem F . Elementy F [[x]] utożsamiamy z nieskończonymi ciągami elementów F . Umawiamy się, że ciąg a0 a1 . . . am−2 am−1 . . . oznacza wzór ∞ X ai x i , i=0 czyli pewien szereg. Dla podkreślenia, że mówiąc o szeregach mamy na myśli wzory, takie szeregi nazywamy formalnymi. Tak więc szeregi (i wielomiany) utożsamiamy z ciągami, których i-ty wyraz jest współczynnikiem przy xi (współczynniki wymieniamy od najmłodszego). Szeregi dodajemy i mnożymy w następujący sposób: ∞ X ai x i + i=0 ∞ X ∞ X bi x i = ! ai x · i=0 (ai + bi )xi , i=0 i=0 i ∞ X ∞ X ! bi x i = i=0 ∞ X ci x i , i=0 gdzie ci = i X aj bi−j . j=0 Wielomian, to szereg formalny, którego wszystkie wyrazy od pewnego miejsca są równe 0. Stopniem wielomianu nazywamy indeks ostatniego niezerowego współczynnika. Stopniem wielomianu zerowego jest −1 (przyjmuje się także, że stopniem wielomianu zerowego jest −∞). Symbol F [x] oznacza zbiór wielomianów (jednej zmiennej x) nad ciałem F , a m F [x] – zbiór wielomianów stopnia mniejszego niż m. Będziemy utożsamiać zbiory {0, 1}m , Z2m i Z2m [x], ale każdy z tych zbiorów powinien się nam kojarzyć z innymi działaniami: Z2m to przestrzeń liniowa z dodawaniem i mnożeniem przez skalary, Z2m [x] to fragment pierścienia Z2 [x] z dodawaniem i mnożeniem wielomianów lub pierścień z dodawaniem i mnożeniem modulo xm − 1. Elementy Z2m [x] możemy też mnożyć przez skalary z Z2 . 1 Słowa kodu cyklicznego K długości m będziemy utożsamiać z wielomianami stopnia < m. Tak więc dla cyklicznego kodu K mamy K ⊆ Z2m [x]. Zauważmy też, że operację shr dla wielomianów definiujemy następującym wzorem: ( x · w(x) jeżeli stopień w(x) jest mniejszy niż m − 1, shr(w(x)) = x · w(x) − xm + 1 w przeciwnym razie. Wzór ten trzeba nieco zmodyfikować w przypadku kodów, które nie są binarne. Lemat 1.1 Załóżmy, że K jest kodem cyklicznym długości m, a w(x) ∈ K jest wielomianem stopnia k. Wtedy k < m oraz 1) xi · w(x) ∈ K dla wszystkich i < m − k, 2) xm−k · w(x) − xm + 1 ∈ K, 3) v(x) · w(x) ∈ K dla dowolnego wielomianu v(x) stopnia < m − k. 2 1.2 Generatory kodów cyklicznych Generatorem kodu cyklicznego K nazywamy niezerowy wielomian g(x) ∈ K możliwie małego stopnia. W razie potrzeby żądamy jeszcze, aby generator miał przy najwyższej potędze współczynnik 1. Lemat 1.2 Jeżeli g(x) jest generatorem kodu cyklicznego K długości m i ma stopień m − k, to K = {w(x) ∈ Z2m [x] : g(x)|w(x)} = {v(x) · g(x) ∈ Z2m [x] : v(x) ∈ Z2k [x]}. Lemat 1.3 Jeżeli g(x) jest generatorem kodu cyklicznego K długości m i ma stopień m − k, to wielomiany g(x), x · g(x), x2 · g(x), . . . , xk−1 · g(x) tworzą bazę K. 2 Wniosek 1.4 Jeżeli g(x) = g0 + g1 x + . . . + gm−k xm−k jest generatorem kodu cyklicznego K długości m, to g0 g1 g2 . . . gm−k 0 0 0 g0 g1 . . . gm−k−1 gm−k 0 0 0 g0 . . . gm−k−2 gm−k−1 gm−k ... 0 0 0 0 0 0 ... ... 0 0 g0 0 g1 g0 ... ... ... ... 0 0 0 0 0 0 . . . gm−k 0 . . . gm−k−1 gm−k jest macierzą generującą kod K. 2 1.2.1 Charakteryzacja generatorów Generatory kodów cyklicznych długości m to dzielniki wielomianu xm − 1. Mamy bowiem Lemat 1.5 Jeżeli g(x) jest generatorem kodu cyklicznego długości m (i ma stopień m − k), to g(x) dzieli xm − 1. Dowód. Z lematu 1.1 punkt 2) wynika, że xk g(x) − xm + 1 jest słowem kodowym, a więc jest wielomianem podzielnym przez g(x). Stąd teza. 2 Lemat 1.6 Jeżeli wielomian g(x) stopnia m − k dzieli xm − 1, to {w(x) · g(x) ∈ Z2m [x] : stopień w(x) jest < k} jest kodem cyklicznym długości m (i wymiaru k), generowanym przez g(x). 1.3 Kodowanie za pomocą kodów cyklicznych Dla kodów cyklicznych mamy dwa naturalne sposoby kodowania informacji. Przypuśćmy, że K jest kodem cyklicznym długości m i ma generator g(x) stopnia m − k. Taki kod jest wymiaru k. Wobec tego, funkcje kodujące przekształcają {0, 1}k w {0, 1}m . Argumenty i wartości funkcji kodujących utożsamiamy z wielomianami. Interesują nas więc różnowartościowe funkcje f : Z2k [x] → K ⊆ Z2m [x]. Jedną z takich funkcji możemy definiować wzorem f (w(x)) = w(x) · g(x). Ciekawszą funkcję kodującą zdefiniujemy wzorem f (w(x)) = xm−k · w(x) − (xm−k · w(x)) mod g(x). Zauważmy, że słowo odpowiadające wielomianowi xm−k · w(x) ma zera na m − k początkowych pozycjach, a dalej ma kolejne współczynniki wielomianu w(x). Odejmując resztę (xm−k · w(x)) mod g(x) zastępujemy początkowe m − k zer jej współczynnikami. Kodowanie polega więc na poprzedzeniu danego słowa współczynnikami wskazanej reszty. Współczynniki te możemy uważać za symbole kontrolne. Tak więc kodując w ten sposób poprzedzamy dane słowo odpowiednio wyliczonymi symbolami kontrolnymi. 1.4 1.4.1 Korygowanie błędów Syndrom W kontekscie kodowania za pomocą kodu cyklicznego generowanego przez g(x), syndromem nazywamy resztę z dzielenia danego (przysłanego) wielomianu przez g(x). Dla kodów cyklicznych mamy oczywista równoważność: syndrom (wystąpienia błędu) (odebranego słowa) jest równy 0 wtedy i tylko wtedy, gdy zostało odebrane słowo kodowe (być może inne niż wysłane). Lemat 1.7 Przypuśćmy, że kod cykliczny wykrywa t błędów i podczas przesyłania słowa kodowego w wystąpiło nie więcej niż t błędów. Syndrom odebranego słowa jest równy 0 wtedy i tylko wtedy, gdy podczas przesyłania nie wystąpiły błędy. 2 1.4.2 Minimalna odległość słów kodów liniowych Lemat 1.8 Jeżeli liniowy kod K ma długość m i wymiar k, to minimalna odległość słów kodowych d(K) spełnia nierówność d(K) ¬ m−k +1. Jeżeli taki kod wykrywa t błędów, to t ¬ m − k. Dowód. Kod liniowy wymiaru k ma k symboli informacyjnych, które możemy dowolnie określić. Bierzemy słowo w, które ma jeden symbol informacyjny równy 1, a pozostałe są równe 0. Takie słowo jest różne od ~0 i ma przynajmniej k − 1 liter równych 0. Mamy więc d(K) ¬ d(w, ~0) ¬ m − (k − 1) = m − k + 1. 2 Lemat 1.9 Jeżeli liniowy, binarny kod K ma długość m, wymiar k > 0 i minimalną odległość słów kodowych d(K) = m − k + 1, to K jest kodem pełnym (K = {0, 1}m ), kodem z bitem parzystości lub kodem powtórzeniowym. Dowód. Będziemy rozważać kilka przypadków. W pierwszym mamy k 2 oraz d(K) = m − k + 1 3. Przedstawiając słowa kodowe będziemy dla uproszczenia zapisu zakładać, że symbole informacyjne znajdują się na pierwszych k pozycjach. Ponieważ k 2, więc do K należą dwa słowa 100 . . . 0ak+1 . . . am oraz 010 . . . 0bk+1 . . . bm . Gdyby ak+1 = bk+1 , . . . oraz am = bm , to suma tych dwóch słów miała by wagę 2 i – wbrew założeniu – zachodziłaby nierówność d(K) ¬ 2. W przeciwnym razie, w jednym z tych słów byłoby k zer i jego waga byłaby ¬ m − k < d(K), co też nie jest możliwe. Tak więc nie ma kodów spełniających pierwszy przypadek. W drugim przypadku rozważamy kody wymiaru 1. Takie kody składają się z dwóch słów: słowa złożonego z samych zer i słowa, które różni się od od zerowego na wszystkich pozycjach, a więc słowa złożonego z samych jedynek. Taki kod jest kodem powtórzeniowym. Jeżeli d(K) = m − k + 1 = 1, to k = m i kod K jest kodem pełnym złożonym z wszystkich słów długości m. Pozostał do rozważenia przypadek, w którym k 2 i d(K) = m − k + 1 = 2. Kody spełniające te założenia mają jeden symbol kontrolny. Zauważmy, że do K muszą należeć słowa 100 . . . 01, 010 . . . 01, 001 . . . 01, . . . oraz 000 . . . 11. Symbole kontrolne tych słów (umieszczone na końcu) muszą być równe 1, gdyż d(K) = 2. Kod wymiaru k zawierający te słowa jest kodem z bitem parzystości. 2 Kody wymienione w powyższym lemacie można uważać za mało istotne. Ten lemat stwierdza więc, że w istotnych przypadkach, jeżeli kod liniowy długości m i wymiaru k wykrywa t błędów, to t < m − k. 1.4.3 Prymitywny algorytm korygujący błędy Zakładamy, że mamy kod cykliczny K długości m, który jest generowany przez wielomian g(x) i koryguje t błędów. Jeżeli podczas przesyłania słów kodowych występuje t błędów, to możemy je korygować w następujący sposób: 1) Dla każdego wzorca błędu o wadze ¬ t obliczamy i zapamiętujemy sam wzorzec i jego syndrom. 2) Dane słowo jest wartością zmiennej w, obliczamy też syndrom s := w mod g(x); 3) jeżeli s = 0 (a więc przesyłanie było bezbłędne), to kończymy działanie algorytmu przyjmując przy tym, że wynikiem obliczeń jest w; 4) jeżeli s jest syndromem wzorca błędów e, obliczonym w punkcie 1), to podstaw w := w + e; 5) wynikiem obliczeń jest słowo w. 1.4.4 Kolejny algorytm korygujący błędy Znowu zakładamy, że kod cykliczny K ma długość m, jest generowany przez wielomian g(x) i koryguje t błędów. Korygując t błędów możemy wykorzystywać istotniej cykliczność kodu: 1) Dla każdego wzorca błędu o wadze ¬ t, z jedynką na ostatniej pozycji (najbardziej znaczącej, odpowiadającej potędze xm−1 ), obliczamy i zapamiętujemy sam wzorzec i jego syndrom. 2) Dane słowo jest wartością zmiennej w, ponadto wykonaj podstawienia i := 0 oraz s := w mod g(x); 3) jeżeli s = 0 (a więc przesyłanie było bezbłędne), to kończymy działanie algorytmu przyjmując przy tym, że wynikiem obliczeń jest w; 4) dopóki syndrom s jest różny od wszystkich syndromów wyliczonych w punkcje 1) oraz i < m wykonuj: (a) w := shr(w); (b) i := i + 1; (c) s := w mod g(x); 5) jeżeli s jest syndromem wzorca błędów e, obliczonym w punkcie 1), to podstaw w := w + e; 6) dla j od i do m − 1 podstaw w := shr(w); 7) wynikiem obliczeń jest słowo w. 1.5 Pęknięcia Wielomian (słowo) e jest wzorcem pęknięcia długości l, jeżeli istnieje i takie, że stopień wielomianu shri (e) jest < l (jeżeli po odpowiednim przesunięciu cyklicznym słowa e niezerowe znaki znajdują się na l początkowych pozycjach). Kod liniowy K wykrywa pęknięcia długości l, jeżeli żaden niezerowy wzorzec pęknięcia długości l nie należy do K. Jeżeli kod liniowy K wykrywa pęknięcia długości l i podczas przesyłania słów z K występuje pęknięcie długości l, to następujący algorytm poprawnie wykrywa błąd: 1) Dane: otrzymane słowo w. 2) Jeżeli w ∈ K, to ” nie wystąpił błąd” 3) w przeciwnym razie, ”podczas przesyłania słowa wystąpił błąd”. Lemat 1.10 Jeżeli kod liniowy K długości n i wymiaru k wykrywa pęknięcia długości l, to n − k l. Dowód. Oczywiście, jest 2l wzorców pęknięć, które same są wielomianami stopnia < l. Niech f przyporządkowuje takiemu wzorcowi p jego warstwę p+K. Nietrudno zauważyć, że ta funkcja jest różnowartościowa. Liczba warstw jest równa 2n−k . Stąd 2l ¬ 2n−k i – ostatecznie – l ¬ n − k. 2 Fakt 1.11 Kody cykliczne długości n i wymiaru k wykrywają pęknięcia długości n − k. 2 Kod liniowy K koryguje pęknięcia długości l, jeżeli żadna niezerowa różnica wzorców pęknięć długości l nie należy do K. Jeżeli kod liniowy K koryguje pęknięcia długości l i podczas przesyłania słów z K występuje najwyżej pęknięcie długości l, to następujący algorytm jest poprawny: 1) Dane: otrzymane słowo w. 2) Znajdź słowo kodowe v takie, że v−w jest pęknięciem długości l. (To powinno się udać, jeżeli informacje przesyłamy tak, że mogą wystąpić najwyżej błędy o wzorcach będących pęknięciami długości l.) 3) Stwierdź, że zostało wysłane słowo kodowe v. Lemat 1.12 Jeżeli kod liniowy K długości n i wymiaru k koryguje pęknięcia długości l, to n − k 2l. Dowód. Oczywiście, 2l ¬ n. W przeciwnym razie każde słowo kodowe byłoby różnicą dwóch pęknięć długości l. Wiemy też, że jest 2l wzorców pęknięć, które same są wielomianami stopnia < l, a także takich, które są wielomianami stopnia l i < l. Wobec tego jest przynajmniej 22l różnic wzorców pęknięć długości l, Niech f przyporządkowuje takiej różnicy r jej warstwę r + K. Nietrudno zauważyć, że ta funkcja jest różnowartościowa. Liczba warstw jest równa 2n−k . Stąd 22l ¬ 2n−k i – ostatecznie – 2l ¬ n − k. 2 1.6 Korygowanie pęknięć Lemat 1.13 Jeżeli kod cykliczny koryguje t błędów i syndrom otrzymanego słowa ma wagę ¬ t, to w takim przypadku błędy można skorygować obliczając sumę otrzymanego słowa i syndromu. Dowód. Załóżmy, że podczas przesyłania słowa w zostały zrobione błędy opisane przez wzorzec e o wadze ¬ t. Wtedy syndromem jest słowo v = (w + e) mod g. Jeżeli syndrom v ma wagę ¬ t, to słowo w + e + v jest słowem kodowym takim, że d(w + e + v, w) ¬ d(w + e + v, w + e) + d(w + e, w) = d(~0, v) + d(~0, e) ¬ 2t. Słowo kodowe kodu korygującego t błędów odległe o ¬ 2t są identyczne, a więc w = w + e + v. 2 Dalej rozważamy kod cykliczny K długości n i wymiaru k, generowany przez g i korygujący pęknięcia długości l. Powyższy lemat sugeruje następującą metodą korygowania pęknięć: 1) Algorytm ”error trapping”. Dane: (przesłane) słowo w. 2) i = 0 3) while (i < n) oraz syndrom słowa shri (w) ma wagę > l do i := i + 1; 4) oblicz v = shri (w)+(shri (w) mod g) (dodaj do słowa shri (w) jego syndrom) 5) przekaż shrn−i (v). Przypuśćmy, że przesłaliśmy słowo u ∈ K i otrzymaliśmy słowo w = u + e. Z własności sposobu przesyłania słów, e jest wzorcem pęknięcia długości l. Bardzo ważne jest to, że przedstawienie w w postaci tej sumy jest jednoznaczne. Wynika to z tego, że kod K koryguje odpowiednie pęknięcia. Wiemy, że l < 2l ¬ n − k i n − k jest stopniem generatora g kodu K. Z definicji pęknięcia wynika, że istnieje i takie, że stopień wielomianu shri (e) jest < l. Obliczmy syndrom shri (w). Mamy shri (w) mod g = shri (u+e) mod g = (shri (u)+shri (e)) mod g = shri (e) mod g = shri (e), gdyż słowo shri (u) jest słowem kodowym na mocy cykliczności kodu K. Stąd otrzymujemy, że pętla while zakończy się wraz ze znalezieniem jakiegoś i, dla którego prawdziwe będą powyższe równości. Wtedy zmienna v przyjmie wartość v = shri (w) + shri (e) = shri (w + e) = shri (u + e + e) = shri (u). Ostatecznie algorytm zakończy działanie wraz z przekazaniem wartości shrn−i (shri (u)) = shrn (u) = u. Tak więc jest to poprawny algorytm korygujący pęknięcia (ale tylko pod warunkiem, że kod K koryguje odpowiednie pęknięcia!). tak więc Lemat 1.14 Jeżeli kod cykliczny K koryguje pęknięcia długości l, to przytoczony algorytm poprawnie koryguje błędy powstające podczas przesyłania słów kodowych. 2 Jeżeli korzystamy z kodu cyklicznego, to przytoczony algorytm można wykorzytać do korygowania pojedyńczego błędu. Jest oczywiste, że jeżeli algorytm koryguje 1 błąd, to także koryguje pęknięcia długości 1. Mamy też Lemat 1.15 Jeżeli K jest kodem cyklicznym długości n wymiaru k, korygującym 2 błędy, oraz 2k < n, to powyższy algorytm poprawnie koryguje 2 błędy. Dowód. Dowód jest analogiczny do dowodu z poprzedniego lematu. 2 Modyfikując trochę powyższy algorytm możemy otrzymać też algorytm korygujący dwa błędy w przypadku, gdy długość kodu n i jego wymiar spełniają równość n = 2k. 1.7 Error trapping w przypadku kodu Golay’a Kodem Golay’a nazywamy cykliczny kod długości 23, wymiaru 12. Przyjmijmy, że g(x) jest generatorem kodu Golay’a stopnia 11. Wiadomo, że kod ten pozwala korygować 3 błędy. Można je korygować stosując następujący algorytm: 1) Dane: przesłane słowo-wielomian w (długości 23, stopnia 22). 2) i := 0; 3) while (i < 23) oraz waga syndromu shri (w) > 3 do i := i + 1; 4) if i < 23 then return( shr23−i (shri (w) + (shri (w) mod g)) ); (udaje się w ten sposób skorygować, jeżeli w danym słowie, po sklejeniu początku z końcem, znajduje się 12 kolejnych zer) 5) zmieniamy wybrany bit słowa w otrzymując słowo w0 (w rzeczywistości kolejno zmieniamy bity tak długo, aż uda nam się skorygować błędy); 6) i := 0; 7) while (i < 23) oraz waga syndromu shri (w) > 2 do i := i + 1; 8) if i < 23 then return( shr23−i (shri (w0 ) + (shri (w0 ) mod g)) ); (zauważmy, że zwracane słowo jest słowem kodowym, które różni się od od słowa w na najwyżej trzech pozycjach. Nie ma innego słowa o tych własnościach, gdyż kod koryguje trzy błędy. Tylko to słowo mogło zostać wysłane). 9) Jeżeli i = 23, to wybieramy i zmieniamy kolejny bit słowa w (wracamy do punktu 5, ale w końcu uda się skorygować błędy: jeżeli wystąpiły 3 błędy, to najbliższe są oddzielone najwyżej sześcioma zerami, zmiana trzeciego pozwoli na skorygowanie dwóch pozostałych, podobnie, jeżeli wystąpiły dwa błędy).