Prezentacja multimedialna
Zapoznaj się z prezentacją. Prześledź działanie programu.
Zapoznaj się z prezentacją, w tym z działaniem programu.

Szyfr płotkowy – rodzaj szyfru przestawieniowego
Szyfr płotkowy jest przykładem szyfru przestawieniowego – w zaszyfrowanej wiadomości obecne są wszystkie znaki użyte w tekście jawnym, zmieniona zostaje jedynie ich pozycja w szyfrogramie. Aby zaszyfrować wiadomość algorytmem szyfru płotkowego, na początku należy wybrać klucz symetryczny, który posłuży do zaszyfrowania i odszyfrowania wiadomości.

W komórkach tabeli umieszczono napis: FONTANNA W PARKU. Litery te umieszczone są w komórkach, tworząc zygzaka.

Sposób działania
W e‑materiale teoretycznym omówiliśmy algorytm szyfrowania płotkowego, w tej prezentacji przeanalizujemy jego implementację w języku Python. W przedstawionym programie zastosujemy funkcję przyjmującą dwa parametry: tekst_do_szyfrowania
oraz klucz
.
W przypadku tego algorytmu kluczem będzie wysokość płotka, czyli w podanym przykładzie: pięć.
Widzimy pełny kod źródłowy funkcji. Podzielony jest na cztery główne kroki, które za chwilę omówimy dokładniej. Zwróćmy uwagę na wiersze: 4., 9., 11., 22., 37., 41. i 48. – w nich zawarte są funkcje print
, dzięki którym możemy obserwować wyniki kolejnych działań algorytmu. W wierszach od 20. do 37. znajduje się główna część programu. Jest to pętla while
, czyli pętla warunkowa działająca dopóty, dopóki zmienna tekst_jawny
zawiera jakikolwiek znak. Na uwagę zasługują również wiersze od 43. do 50., w których realizujemy odczyt kolejnych znaków szyfrogramu i złożenie zaszyfrowanego komunikatu.
Kod
def szyfruj_plotkowy(tekst_do_szyfrowania, klucz):
# Krok 1. Usuń spacje i zmień wszystkie litery na wielkie.
tekst_jawny = "".join([litera.upper() for litera in tekst_do_szyfrowania if litera != " "])
print(f"Zaszyfrujemy: {tekst_jawny}")
# Krok 2. Sprawdź i zapamiętaj liczbę znaków do szyfrowania.
liczba_znakow = len(tekst_jawny)
plotek = [[" " for _ in range(klucz)] for _ in range(liczba_znakow)]
print(f"Płotek wygenerowany: {plotek}")
for wiersz_plotka in plotek:
print(wiersz_plotka)
# Krok 3. Umieść tekst jawny w tablicy dwuwymiarowej.
# flaga kierunek = 1 - wypełniamy płotek w dół
# flaga kierunek = -1 - wypełniamy płotek w górę
kierunek = 1 # rozpoczynamy wypełnianie z góry na dół
znak = 0 # indeks sprawdzanego znaku
wiersz = 0 # nr wiersza
while tekst_jawny:
znak_tekstu = tekst_jawny[0] # pierwszy znak
print(f"znak_tekstu={znak_tekstu}/kierunek={kierunek}/znak={znak}/wiersz={wiersz}")
plotek[znak][wiersz] = znak_tekstu
znak += 1
# teraz sprawdzamy warunek dla flagi
if wiersz == klucz-1: # w pythonie indeks zaczynamy liczyć od zera, więc ostatni -1
kierunek = -1
elif wiersz == 0:
kierunek = 1
# teraz w zależności od flagi zwiększamy lub zmniejszamy
wiersz += kierunek
# pozostawiamy resztę tekstu jawnego do zaszyfrowania
tekst_jawny = tekst_jawny[1:] # reszta jawnego tekstu, bez pierwszego znaku
print(f"plotek={plotek}")
# Krok 4. Odczytaj zaszyfrowaną wiadomość.
for wiersz_plotka in plotek:
print(wiersz_plotka)
szyfrogram = ""
for wiersz in range(klucz):
for wiersz_plotka in plotek:
znak = wiersz_plotka[wiersz]
if znak != " ":
print(znak, end=":")
szyfrogram += znak
print()
# Zwracamy rezultat
return szyfrogram
print(szyfruj_plotkowy("Fontanna w parku", 5))
Krok 1. Usuń spacje i zmień wszystkie litery na wielkie
Rozpocznijmy analizę od efektu działania – widzimy napis FONTANNAWPARKU
, zapisany wielkimi literami i bez spacji. Podczas gdy funkcję szyfruj_plotkowy
wywołaliśmy, podając jako argument napis zawierający zarówno spacje, jak i małe litery. Zmiana ta została przeprowadzona w wierszu 3. kodu. Zastosowano tu metodę join
, używaną dla obiektów tekstowych – w omawianym przypadku obiekt reprezentują dwa cudzysłowy na lewo od kropki po lewej stronie metody. Jej argumentem jest wyrażenie listowe, generujące listę znaków zamienionych na wielkie litery metodą upper
na podstawie kolekcji wejściowej, czyli szyfrowanego ciągu znaków. Dzięki zastosowaniu klauzuli if
zamieniamy tylko te znaki, które nie są spacją.
Możemy to prześledzić na zrzucie ekranu z aplikacji IDLE
. Widzimy kilka poleceń. Pierwszym z nich jest zastosowanie metody join
– doklejamy w niej do pustego ciągu tekstowego kolejne elementy z listy.
Widzimy również generator listowy, który iteruje po kolejnych literach napisu. W ten sposób ciąg zamieniany jest na listę pojedynczych znaków. W kolejnym generatorze widzimy użycie metody upper
, przeprowadzającej zamianę małych liter na wielkie. Następny generator zawiera klauzulę if
, dzięki czemu na wynikowej liście znajdują się elementy spełniające określony w niej warunek. Ostatnie polecenie łączy metodę join
z generatorem listowym.
Efekt działania
print(szyfruj_plotkowy("Fontanna w parku"))
# Zaszyfrujemy: FONTANNAWPARKU
Kod
def szyfruj_plotkowy(tekst_do_szyfrowania, klucz):
# Krok 1. Usuń spacje i zmień wszystkie litery na wielkie
tekst_jawny = "".join([litera.upper() for litera in tekst_do_szyfrowania if litera != " "])
print(f"Zaszyfrujemy: {tekst_jawny}")
![Ilustracja przedstawia kod. Wiersz pierwszy: Python 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux. Wiesz drugi: Type: "help", "copyright", "credits" or "license()" for more information. Trzeci wiersz: "".join(["A", "B", "c", "d"]). Wiersz czwarty: 'ABcd'. Wiersz piąty: [a for a in "tekst jawny"]. Wiersz szósty: ['t', 'e', 'k', 's', 't', ' ', 'j', 'a', 'w', 'n', 'y']. Wiersz siódmy: [ a.upper() for a in "tekst jawny"]. Wiersz ósmy: ['T', 'E', 'K', 'S', 'T', ' ', 'J', 'A', 'W', 'N', 'Y']. Wiersz dziewiąty: [a.upper() for a in "tekst jawny" if a !=" "]. Wiersz dziesiąty: ['T', 'E', 'K', 'S', 'T', 'J', 'A', 'W', 'N', 'Y']. Wiersz jedenasty: "".join ([ a. upper() for a in "tekst jawny" if a !=" "]). Wiersz dwunasty: 'TEKSTJAWNY'.](https://static.zpe.gov.pl/portal/f/res-minimized/RpYPqTD8J4IAV/1690814636/gwQqjxaF0eWYmndrY3WtUpDdMtfzBqN9.png)
Krok 2. Sprawdź i zapamiętaj liczbę znaków do szyfrowania
W kolejnej części funkcji tworzymy płotek, a więc listę dwuwymiarową, która zawiera tyle list o wielkości klucza, ile jest liter w szyfrowanym napisie.
Ponownie spójrzmy na zrzut ekranu z aplikacji IDLE. Widzimy kilka poleceń. Pierwszym z nich jest generator listowy. Ma on składnię analogiczną do pętli iteracyjnej for
. Pamiętajmy, że w przypadku generatora listowego nie korzystamy z metody append
dodającej nowe elementy do listy. Dodatkowo za słowem kluczowym for
występuje znak podkreślenia – w języku Python używamy go do oznaczenia niepotrzebnej zmiennej. W kolejnym poleceniu mamy ten sam generator listowy, lecz zamiast podkreślenia znajduje się tu zmienna x
, a wynik otrzymujemy identyczny. Wynika z tego, że zmienna ta nie wpływa na wynik. Widzimy również złożenie jednego generatora listowego w drugim, dzięki czemu tworzona jest lista dwuwymiarowa. Ostatnie wywołanie to standardowa pętla iteracyjna, w której wyświetlamy kolejne elementy listy dwuwymiarowej – są to po prostu listy.
![Ilustracja przedstawia kod. Wiersz pierwszy: Python 3.10.8 ( main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux. Wiesz drugi: Type: "help", "copyright", "credits" or "license()" for more information. Trzeci wiersz: ["x" for _in range(5) ]. Czwarty wiersz: ['x', 'x', 'x', 'x', 'x']. Piąty wiersz: "x" for x in range(5) ]. Szósty wiersz: ['x', 'x', 'x', 'x', 'x']. Siódmy wiersz: [ [ "x" for x in range(5) ] for _ in range(3) ]. Ósmy wiersz: [['x', 'x', 'x', 'x', 'x'], ['x', 'x', 'x', 'x', 'x'], ['x', 'x', 'x', 'x', 'x']]. Dziewiąty wiersz: lista_dwa = [ [ "x" for x in range(5)] for _ in range(3) ]. Dziesiąty wiersz: for element in lista_dwa:. Jedenasty wiersz: print(element). Dwunasty i trzynasty wiersz pusty. Piętnasty, szesnasty i siedemnasty wiersz są takie same: ['x', 'x', 'x', 'x', 'x'].](https://static.zpe.gov.pl/portal/f/res-minimized/RmqNAS4M9QAio/1690814637/2ADV8RmeNNVypsV3yrf9NIRhV5fhWD9N.png)
Zwróć uwagę na to, że w przypadku programu generator listowy wypełnia listę nie literami x, a znakami spacji.
Kod
# Krok 2. Sprawdź i zapamiętaj liczbę znaków do szyfrowania
liczba_znakow = len(tekst_jawny)
plotek = [[" " for _ in range(klucz)] for _ in range(liczba_znakow)]
print(f"Płotek wygenerowany: {plotek}")
for wiersz_plotka in plotek:
print(wiersz_plotka)
Efekt działania
Płotek wygenerowany: [[' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ']]
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
Krok 3. Umieść tekst jawny w tablicy dwuwymiarowej
Pobieramy kolejne znaki z tekstu do zaszyfrowania (widoczne jest to w wierszu 8.) i zgodnie z zasadą płotka przypisujemy je do odpowiednich elementów listy dwuwymiarowej (wiersz 10.). Następnie w wierszach od 14. do 17. sprawdzamy, jak zmienić flagę kierunek
określającą, czy kolejna litera ma być poniżej czy powyżej poprzedniej. Warte uwagi rozwiązanie zastosowane jest w wierszu 23. Do zmiennej przypisujemy kolejną zmienną, lecz odwołujemy się do niej jak do listy, używając metody wycinków. Sposób działania tego mechanizmu widzimy na zrzucie z aplikacji IDLE: do zmiennej tekstowej przypisujemy wartość – słowo Adam
. Za pomocą funkcji id
sprawdzamy jej identyfikator, a następnie przypisujemy do niej wycinek wszystkich znaków: począwszy od indeksu 1 do końca. W ten sposób odcinamy pierwszy znak mający indeks 0. Widzimy nową wartość oraz identyfikator, który jest różny od poprzedniego. Python utworzył zupełnie nową zmienną, mającą jednak tę samą nazwę.
Kod
# flaga kierunek = 1 - wypełniamy płotek w dół
# flaga kierunek = -1 - wypełniamy płotek w górę
kierunek = 1 # rozpoczynamy wypełnianie z góry na dół
znak = 0 # indeks informuj
wiersz = 0 # nr wiersza
while tekst_jawny:
znak_tekstu = tekst_jawny[0] # pierwszy znak
print(f"znak_tekstu={znak_tekstu}/kierunek={kierunek}/znak={znak}/wiersz={wiersz}")
plotek[znak][wiersz] = znak_tekstu
znak += 1
# teraz sprawdzamy warunek dla flagi
if wiersz == klucz-1: # w pythonie indeks zaczynamy liczyć od zera, więc ostatni -1
kierunek = -1
elif wiersz == 0:
kierunek = 1
# teraz w zależności od flagi zwiększamy lub zmniejszamy
wiersz += kierunek
# pozostawiamy resztę tekstu jawnego do zaszyfrowania
tekst_jawny = tekst_jawny[1:] # reszta jawnego tekstu, bez pierwszego znaku
print(f"plotek={plotek}")
![Ilustracja przedstawia kod. Wiersz pierwszy: Python 3.10.8 ( main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux. Wiesz drugi: Type: "help", "copyright", "credits" or "license()" for more information. Trzeci wiersz: tekst_jawny = "Adam". Czwarty wiersz: id(tekst_jawny). Wiersz piąty: 140491968772144. Szósty wiersz: tekst_jawny = tekst_jawny[1:]. Siódmy wiersz: tekst_jawny. Ósmy wiersz: 'dam'. Dziewiąty wiersz: id(tekst_jawny). Dziesiąty wiersz: 140491971563504.](https://static.zpe.gov.pl/portal/f/res-minimized/R2aXfgr1OGTFp/1690814638/1MVDctPLMS4HddMXypSCVtwTddPf2Pr2.png)
Litery zostały rozmieszczone na płotku. Zauważmy, że litera F umieszczona jest w pierwszym wierszu, a więc w pierwszej wewnętrznej liście w strukturze dwuwymiarowej listy. Następnie widzimy, w których miejscach w kolejnych listach są umieszczane inne litery. Flaga kierunek
zmienia swój znak w momencie, kiedy dochodzimy do końca list i płotek zawraca. Przeanalizuj kod programu i jego efekty.
Efekt działania
znak_tekstu=F/kierunek=1/znak=0/wiersz=0
plotek=[
['F', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ']]
znak_tekstu=O/kierunek=1/znak=1/wiersz=1
znak_tekstu=N/kierunek=1/znak=2/wiersz=2
znak_tekstu=T/kierunek=1/znak=3/wiersz=3
znak_tekstu=A/kierunek=1/znak=4/wiersz=4
znak_tekstu=N/kierunek=-1/znak=5/wiersz=3
znak_tekstu=N/kierunek=-1/znak=6/wiersz=2
znak_tekstu=A/kierunek=-1/znak=7/wiersz=1
znak_tekstu=W/kierunek=-1/znak=8/wiersz=0
znak_tekstu=P/kierunek=1/znak=9/wiersz=1
plotek=[
['F', ' ', ' ', ' ', ' '],
[' ', 'O', ' ', ' ', ' '],
[' ', ' ', 'N', ' ', ' '],
[' ', ' ', ' ', 'T', ' '],
[' ', ' ', ' ', ' ', 'A'],
[' ', ' ', ' ', 'N', ' '],
[' ', ' ', 'N', ' ', ' '],
[' ', 'A', ' ', ' ', ' '],
['W', ' ', ' ', ' ', ' '],
[' ', 'P', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ']]
znak_tekstu=A/kierunek=1/znak=10/wiersz=2
znak_tekstu=R/kierunek=1/znak=11/wiersz=3
znak_tekstu=K/kierunek=1/znak=12/wiersz=4
znak_tekstu=U/kierunek=-1/znak=13/wiersz=3
Krok 4. Odczytaj zaszyfrowaną wiadomość
Widzimy cały płotek i rozmieszczone w nim litery. Aby otrzymać ten efekt, stosujemy pętlę iteracyjną.
Kod
# Krok 4. Odczytaj zaszyfrowaną wiadomość.
for wiersz_plotka in plotek:
print(wiersz_plotka)
Efekt działania
['F', ' ', ' ', ' ', ' ']
[' ', 'O', ' ', ' ', ' ']
[' ', ' ', 'N', ' ', ' ']
[' ', ' ', ' ', 'T', ' ']
[' ', ' ', ' ', ' ', 'A']
[' ', ' ', ' ', 'N', ' ']
[' ', ' ', 'N', ' ', ' ']
[' ', 'A', ' ', ' ', ' ']
['W', ' ', ' ', ' ', ' ']
[' ', 'P', ' ', ' ', ' ']
[' ', ' ', 'A', ' ', ' ']
[' ', ' ', ' ', 'R', ' ']
[' ', ' ', ' ', ' ', 'K']
[' ', ' ', ' ', 'U', ' ']
Krok 5. Zbuduj zaszyfrowaną wiadomość i zwróć ją
Używamy kolejnych indeksów w zależności od klucza, a więc drugiego parametru funkcji. W ten sposób sprawdzamy we wszystkich listach wewnętrznych płotka, czy na kolejnej pozycji znajduje się znak inny niż spacja. Jeśli tak, wypisujemy ten znak na ekranie, stosując dodatkowy parametr funkcji print
o nazwie end
– przypisujemy mu znak dwukropka. Wówczas w pętli wszystkie znaki znajdujące się na danym indeksie będą wypisane w jednej linii. Dodatkowo dodajemy ten znak do zmiennej szyfrogram
, którą zwracamy za pomocą słowa kluczowego return
na końcu funkcji. W ten sposób uzyskujemy zaszyfrowany tekst. Na zrzucie ekranu z aplikacji IDLE znajduje się wywołanie pełnej funkcji z usuniętymi pewnymi funkcjami print
. Widzimy tu strukturę listy dwuwymiarowej i rozmieszczenie liter.
Kod
szyfrogram = ""
for wiersz in range(klucz):
for wiersz_plotka in plotek:
znak = wiersz_plotka[wiersz]
if znak != " ":
print(znak, end=":")
szyfrogram += znak
print()
# Zwracamy rezultat
return szyfrogram
Efekt działania
F:W:
O:A:P:
N:N:A:
T:N:R:U:
A:K:
FWOAPNNATNRUAK
![Ilustracja przedstawia kod. Wiersz pierwszy: Python 3.10.8 ( main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux. Wiesz drugi: Type: "help", "copyright", "credits" or "license()" for more information. Trzeci wiersz: pusty. Czwarty wiersz: ================ RESTART: /home/python/skrypt_szyfr_plotkowy.py ================. Wiersz piąty: szyfruj_plotkowy("Fontanna w parku"). Wiersz szósty: ['F', ' ', ' ', ' ', ' ']. Wiersz siódmy: [' ', 'O', ' ', ' ', ' ']. Wiersz ósmy: [' ', ' ', 'N', ' ', ' ']. Wiersz dziewiąty: [' ', ' ', ' ', 'T', ' ']. Wiersz dziesiąty: [' ', ' ', ' ', ' ', 'A']. Wiersz jedenasty: [' ', ' ', ' ', ' N', ' ']. Wiersz dwunasty: [' ', ' ', 'N', ' ', ' ']. Wiersz trzynasty: [' ', 'A', ' ', ' ', ' ']. Wiersz czternasty: ['W', ' ', ' ', ' ', ' ']. Wiersz piętnasty: [' ', 'P', ' ', ' ', ' ']. Wiersz szesnasty: [' ', ' ', 'A', ' ', ' ']. Wiersz siedemnasty: [' ', ' ', ' ', 'R', ' ']. Wiersz osiemnasty: [' ', ' ', ' ', ' ', 'K']. Wiersz dziewiętnasty: [' ', ' ', ' ', 'U', ' ']. Wiersz dwudziesty: F:W:. Wiersz dwudziesty pierwszy: O:A:P:. Wiersz dwudziesty drugi: N:N:A:. Wiersz dwudziesty trzeci: T:N:R:U:. Wiersz dwudziesty czwarty: A:K:. Wiersz dwudziesty piąty: 'FWOAPNNATNRUAK'.](https://static.zpe.gov.pl/portal/f/res-minimized/R11GB2dTjC7wq/1690814640/17J1jvsNO4dNvP7SVYHqf5ZzxeY8YN8n.png)
Zaszyfruj metodą płotkową tekst Hic‑sunt‑leones
, używając klucza o wartości 3. Korzystaj z rozwiązania przedstawionego w prezentacji.
Specyfikacja problemu:
Dane:
slowo
– łańcuch znaków do zaszyfrowaniaklucz
– liczba naturalna; klucz szyfru
Wynik:
szyfr
– zaszyfrowany łańcuch znakówRBQgYZDRz6N6c xxxx