Uogólniony szyfr Cezara – implementacja w języku Python
W przedstawionej implementacji przyjmiemy następujące założenia:
jako alfabetu będziemy używali alfabetu łacińskiego zawierającego liter zapisanych za pomocą kodu ASCIIASCIIASCII,
nie uwzględniamy wielkości liter, przed zaszyfrowaniem zamienimy wprowadzony tekst na wielkie litery,
podczas szyfrowania wszystkie znaki niebędące wielkimi literami pozostawiamy w szyfrogramieszyfrogramszyfrogramie,
klucz może być dowolną liczbą całkowitą.
Specyfikacja algorytmu
Polecenie 1
Napisz program, który zaszyfruje podany tekst za pomocą uogólnionego szyfru Cezaraszyfr Cezaraszyfru Cezara i wypisze go na ekranie.
Specyfikacja problemu:
Dane:
tekst – ciąg znaków do zaszyfrowania
klucz – liczba całkowita określająca przesunięcie
Wynik:
ciąg znaków reprezentujący zaszyfrowany tekst
Zaczniemy zapisania nagłówka funkcji szyfruj.
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
def szyfruj(tekst, klucz):
Pierwszy argument przyjmowany przez funkcję to łańcuch znaków, który mamy zaszyfrować, a drugi – wartość przesunięcia. Pamiętajmy, że przesunięcie może być dowolną liczbą całkowitą.
Ponieważ klucz w wersji uogólnionej może być dowolną liczbą całkowitą, pierwszym krokiem będzie znormalizowanie go.
Ważne!
Możemy nie normalizować klucza, ale w takim wypadku musimy rozbudować program o dodatkowe instrukcje (obsługujące różne wartości klucza).
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły klucz procent 26 plus 26 zamknij nawias okrągły procent 26.
Założyliśmy, że program nie będzie uwzględniał wielkości liter, zatem przed przystąpieniem do szyfrowania musimy zamienić ewentualne małe litery na wielkie.
Wykorzystamy pętlę for. Przeiterujemy przez wszystkie znaki w szyfrowanym tekście, by sprawdzić, które z nich są małymi literami. W instrukcji warunkowej sprawdzimy, czy wartość kodu ASCII danego znaku z szyfrowanego łańcucha zawiera się w zakresie, do którego należą kody ASCII małych liter alfabetu łacińskiego (czyli od a do z).
Jeżeli instrukcja warunkowa zwróci wartość true (warunek jest spełniony, czyli znak jest małą literą), kod zmienia małą literę na dużą literę.
Wykorzystamy funkcje ord oraz chr.
Funkcja ord(znak) zwraca wartość liczbową danego znaku przechowywanego w zmiennej znak.
Funkcja chr przeprowadza operację odwrotną – wartość liczbową zamienia na odpowiadający jej znak.
By zamienić małą literę na wielką, zaczniemy od przekształcenia znaku – jego wartość liczbową uzyskujemy, wykorzystując funkcję ord(znak). Następnie od uzyskanej wartości odejmujemy . Robimy tak, ponieważ w tabeli kodów ASCII duże litery są dokładnie pozycje przed małymi literami, np. kod ASCII dla litery a to , a dla A to . Zatem odejmowanie od kodu małej litery zamienia ją na dużą literę.
W kolejnym kroku uzyskany kod ASCII przekształcamy na znak, wykorzystując funkcję chr.
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły klucz procent 26 plus 26 zamknij nawias okrągły procent 26.
Linia 3. zaszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 5. for znak in tekst dwukropek.
Linia 6. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 7. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
def szyfruj(tekst, klucz):
klucz = (klucz % 26 + 26) % 26
zaszyfrowany_tekst = ""
for znak in tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
Program ma szyfrować wyłącznie litery, zatem inne znaki (spacje czy znaki interpunkcyjne oraz cyfry) nie powinny być szyfrowane. Zapiszemy zatem kolejną instrukcję warunkową.
Ważne!
Uogólniony szyfr Cezara powinien działać niezależnie od wartości klucza. Musimy zatem brać pod uwagę trzy przypadki:
wartość zmiennej klucz jest większa niż ;
wartość zmiennej klucz jest równa ;
wartość zmiennej klucz jest mniejsza od .
Jak zostało powiedziane, nie musimy rozpisywać dodatkowych instrukcji, ponieważ doprowadziliśmy do normalizacji wartości klucza – zawsze znajduje się w zakresie .
Jeśli znak będzie wielką literą, czyli jego kod numeryczny będzie zawierał się w przedziale kodów numerycznych znaków <A; Z>, zostanie zaszyfrowany. Szyfrowany znak będziemy przechowywać w zmiennej zaszyfrowany_znak. Przypiszemy jej odpowiednią wartość. Przedstawmy to na przykładzie.
Jeśli znak będzie wielką literą, czyli jego kod numeryczny będzie zawierał się w przedziale kodów numerycznych znaków , zostanie zaszyfrowany. Szyfrowany znak będziemy przechowywać w zmiennej zaszyfrowany_znak. Przypiszemy jej odpowiednią wartość. Przedstawmy to na przykładzie.
Najpierw przekształcimy znak na wartość liczbową.
Naszą przykładową literą będzie litera . Jej wartość liczbowa to .
Następnie odejmiemy od niej liczbę . Dzięki temu wartość liczbowa znaku będzie wynosić , – , – itd.
Od odejmujemy . Otrzymany wynik to – gdyby alfabet traktować jako tablicę znaków indeksowaną od , litera to element o indeksie .
W kolejnym kroku dodamy do otrzymanego wyniku wartość zmiennej klucz, czyli przesunięcia.
Załóżmy, że nasz klucz (po normalizacji) wynosi . Wiemy zatem, że litera powinna zostać przekształcona na literę . Do liczby dodajemy . Otrzymany wynik to .
Przedostatnim krokiem jest wykonanie operacji modulo – w ten sposób upewnimy się, że wartość zawiera się w zakresie od do .
Operacja modulo daje .
Na końcu dodamy liczbę , tym samym przywracając wartość do zakresu kodów ASCII.
Suma liczb oraz wynosi . Jest to kod ASCII zaszyfrowanego znaku. Po sprawdzeniu w tablicy ASCII wiemy, że jest to kod litery T, zatem szyfrowanie przebiegło poprawnie.
Ostatnim krokiem jest przekształcenie kodu ASCII do znaku, który zostaje przypisany zmiennej zaszyfrowany_znak.
Dodajemy wartość zmiennej zaszyfrowany_znak na końcu łańcucha znaków zaszyfrowany_tekst.
Jeśli sprawdzany znak nie jest wielką literą alfabetu łacińskiego, w niezmienionej formie dodajemy go na końcu łańcucha znaków zaszyfrowany_tekst
Po zaszyfrowaniu wszystkich znaków zwracamy łańcuch znaków zaszyfrowany_tekst.
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły klucz procent 26 plus 26 zamknij nawias okrągły procent 26.
Linia 3. zaszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 5. for znak in tekst dwukropek.
Linia 6. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 7. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
Linia 8. if apostrof A apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof Z apostrof dwukropek.
Linia 9. zaszyfrowany podkreślnik znak znak równości chr otwórz nawias okrągły otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 65 plus klucz zamknij nawias okrągły procent 26 plus 65 zamknij nawias okrągły.
Linia 10. zaszyfrowany podkreślnik tekst plus znak równości zaszyfrowany podkreślnik znak.
Linia 11. else dwukropek.
Linia 12. zaszyfrowany podkreślnik tekst plus znak równości znak.
Linia 14. return zaszyfrowany podkreślnik tekst.
def szyfruj(tekst, klucz):
klucz = (klucz % 26 + 26) % 26
zaszyfrowany_tekst = ""
for znak in tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
if 'A' <= znak <= 'Z':
zaszyfrowany_znak = chr((ord(znak) - 65 + klucz) % 26 + 65)
zaszyfrowany_tekst += zaszyfrowany_znak
else:
zaszyfrowany_tekst += znak
return zaszyfrowany_tekst
Kod programu
Na koniec umieszczamy wywołania funkcji szyfruj.
Działanie programu przetestujemy dla łańcucha znaków Sklepy cynamonowe t. 2 oraz klucza o wartości .
Cały kod programu:
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły klucz procent 26 plus 26 zamknij nawias okrągły procent 26.
Linia 3. zaszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 5. for znak in tekst dwukropek.
Linia 6. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 7. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
Linia 8. if apostrof A apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof Z apostrof dwukropek.
Linia 9. zaszyfrowany podkreślnik znak znak równości chr otwórz nawias okrągły otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 65 plus klucz zamknij nawias okrągły procent 26 plus 65 zamknij nawias okrągły.
Linia 10. zaszyfrowany podkreślnik tekst plus znak równości zaszyfrowany podkreślnik znak.
Linia 11. else dwukropek.
Linia 12. zaszyfrowany podkreślnik tekst plus znak równości znak.
Linia 14. return zaszyfrowany podkreślnik tekst.
Linia 16. tekst znak równości cudzysłów Sklepy cynamonowe t kropka 2 cudzysłów.
Linia 17. klucz znak równości 5.
Linia 19. tekst znak równości szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły.
Linia 20. print otwórz nawias okrągły tekst zamknij nawias okrągły.
def szyfruj(tekst, klucz):
klucz = (klucz % 26 + 26) % 26
zaszyfrowany_tekst = ""
for znak in tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
if 'A' <= znak <= 'Z':
zaszyfrowany_znak = chr((ord(znak) - 65 + klucz) % 26 + 65)
zaszyfrowany_tekst += zaszyfrowany_znak
else:
zaszyfrowany_tekst += znak
return zaszyfrowany_tekst
tekst = "Sklepy cynamonowe t. 2"
klucz = 5
tekst = szyfruj(tekst, klucz)
print(tekst)
Wynik działania programu: XPQJUD HDSFRTSTBJ Y. 2
Deszyfrowanie
Specyfikacja problemu:
Dane:
zaszyfrowany_tekst – ciąg znaków do odszyfrowania
klucz – liczba całkowita określająca przesunięcie
Wynik:
ciąg znaków reprezentujący odszyfrowany tekst
Szyfr Cezara jest szyfrem symetrycznym – do szyfrowania i deszyfrowania używamy tego samego klucza, oraz podstawieniowym – polega na zastępowaniu znaku tekstu jawnegotekst jawnytekstu jawnego przesuniętym w zapętlonym alfabecie o długość klucza innym znakiem. Z tego wynika, że deszyfrowanie to operacja odwrotna do szyfrowania i polega na przesuwaniu znaku w zapętlonym alfabecie w odwrotnym kierunku niż podczas szyfrowania.
Funkcja deszyfrująca wygląda następująco:
Linia 1. def deszyfruj otwórz nawias okrągły zaszyfrowany podkreślnik tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły otwórz nawias okrągły minus klucz procent 26 plus 26 zamknij nawias okrągły procent 26 zamknij nawias okrągły.
Linia 3. odszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 5. for znak in zaszyfrowany podkreślnik tekst dwukropek.
Linia 6. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 7. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
Linia 8. if apostrof A apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof Z apostrof dwukropek.
Linia 9. odszyfrowany podkreślnik znak znak równości chr otwórz nawias okrągły otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 65 plus klucz zamknij nawias okrągły procent 26 plus 65 zamknij nawias okrągły.
Linia 10. odszyfrowany podkreślnik tekst plus znak równości odszyfrowany podkreślnik znak.
Linia 11. else dwukropek.
Linia 12. odszyfrowany podkreślnik tekst plus znak równości znak.
Linia 14. return odszyfrowany podkreślnik tekst.
def deszyfruj(zaszyfrowany_tekst, klucz):
klucz = ((-klucz % 26 + 26) % 26)
odszyfrowany_tekst = ""
for znak in zaszyfrowany_tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
if 'A' <= znak <= 'Z':
odszyfrowany_znak = chr((ord(znak) - 65 + klucz) % 26 + 65)
odszyfrowany_tekst += odszyfrowany_znak
else:
odszyfrowany_tekst += znak
return odszyfrowany_tekst
Jej wywołanie odbywa się z użyciem tego samego klucza, ale przesunięcie jest w kierunku przeciwnym, zatem przed wartością klucza dodajemy znak minusa.
Kompletny kod programu, który najpierw zaszyfruje łańcuch znaków, a następnie go odszyfruje:
Linia 1. def szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 2. klucz znak równości otwórz nawias okrągły klucz procent 26 plus 26 zamknij nawias okrągły procent 26.
Linia 3. zaszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 5. for znak in tekst dwukropek.
Linia 6. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 7. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
Linia 8. if apostrof A apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof Z apostrof dwukropek.
Linia 9. zaszyfrowany podkreślnik znak znak równości chr otwórz nawias okrągły otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 65 plus klucz zamknij nawias okrągły procent 26 plus 65 zamknij nawias okrągły.
Linia 10. zaszyfrowany podkreślnik tekst plus znak równości zaszyfrowany podkreślnik znak.
Linia 11. else dwukropek.
Linia 12. zaszyfrowany podkreślnik tekst plus znak równości znak.
Linia 14. return zaszyfrowany podkreślnik tekst.
Linia 16. def deszyfruj otwórz nawias okrągły zaszyfrowany podkreślnik tekst przecinek klucz zamknij nawias okrągły dwukropek.
Linia 17. klucz znak równości otwórz nawias okrągły otwórz nawias okrągły minus klucz procent 26 plus 26 zamknij nawias okrągły procent 26 zamknij nawias okrągły.
Linia 18. odszyfrowany podkreślnik tekst znak równości cudzysłów cudzysłów.
Linia 20. for znak in zaszyfrowany podkreślnik tekst dwukropek.
Linia 21. if apostrof a apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof z apostrof dwukropek.
Linia 22. znak znak równości chr otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 32 zamknij nawias okrągły.
Linia 23. if apostrof A apostrof otwórz nawias ostrokątny znak równości znak otwórz nawias ostrokątny znak równości apostrof Z apostrof dwukropek.
Linia 24. odszyfrowany podkreślnik znak znak równości chr otwórz nawias okrągły otwórz nawias okrągły ord otwórz nawias okrągły znak zamknij nawias okrągły minus 65 plus klucz zamknij nawias okrągły procent 26 plus 65 zamknij nawias okrągły.
Linia 25. odszyfrowany podkreślnik tekst plus znak równości odszyfrowany podkreślnik znak.
Linia 26. else dwukropek.
Linia 27. odszyfrowany podkreślnik tekst plus znak równości znak.
Linia 29. return odszyfrowany podkreślnik tekst.
Linia 31. tekst znak równości cudzysłów Sklepy cynamonowe t kropka 2 cudzysłów.
Linia 32. klucz znak równości 5.
Linia 34. tekst znak równości szyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły.
Linia 35. print otwórz nawias okrągły cudzysłów Zaszyfrowany tekst dwukropek cudzysłów przecinek tekst zamknij nawias okrągły.
Linia 37. tekst znak równości deszyfruj otwórz nawias okrągły tekst przecinek klucz zamknij nawias okrągły.
Linia 38. print otwórz nawias okrągły cudzysłów Odszyfrowany tekst dwukropek cudzysłów przecinek tekst zamknij nawias okrągły.
def szyfruj(tekst, klucz):
klucz = (klucz % 26 + 26) % 26
zaszyfrowany_tekst = ""
for znak in tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
if 'A' <= znak <= 'Z':
zaszyfrowany_znak = chr((ord(znak) - 65 + klucz) % 26 + 65)
zaszyfrowany_tekst += zaszyfrowany_znak
else:
zaszyfrowany_tekst += znak
return zaszyfrowany_tekst
def deszyfruj(zaszyfrowany_tekst, klucz):
klucz = ((-klucz % 26 + 26) % 26)
odszyfrowany_tekst = ""
for znak in zaszyfrowany_tekst:
if 'a' <= znak <= 'z':
znak = chr(ord(znak) - 32)
if 'A' <= znak <= 'Z':
odszyfrowany_znak = chr((ord(znak) - 65 + klucz) % 26 + 65)
odszyfrowany_tekst += odszyfrowany_znak
else:
odszyfrowany_tekst += znak
return odszyfrowany_tekst
tekst = "Sklepy cynamonowe t. 2"
klucz = 5
tekst = szyfruj(tekst, klucz)
print("Zaszyfrowany tekst:", tekst)
tekst = deszyfruj(tekst, klucz)
print("Odszyfrowany tekst:", tekst)
Wynik działania programu:
Linia 1. Zaszyfrowany tekst dwukropek XPQJUD HDSFRTSTBJ Y kropka 2.
Linia 2. Odszyfrowany tekst dwukropek SKLEPY CYNAMONOWE T kropka 2.
Zaszyfrowany tekst: XPQJUD HDSFRTSTBJ Y. 2
Odszyfrowany tekst: SKLEPY CYNAMONOWE T. 2
Słownik
ASCII
ASCII
sposób kodowania znaków, który różnym znakom, w tym małym i wielkim literom alfabetu języka łacińskiego, cyfrom, znakom przestankowym i białym, przyporządkowuje liczby całkowite z zakresu <0; 127>
normalizacja
normalizacja
proces, którego celem jest takie przekształcenie klucza, by należał do zakresu <0; 25>
szyfr Cezara
szyfr Cezara
rodzaj szyfru podstawieniowego, w którym każda litera tekstu jawnego (niezaszyfrowanego) zastępowana jest inną – oddaloną od niej o stałą liczbę pozycji w alfabecie – literą (szyfr monoalfabetyczny), przy czym kierunek zamiany musi być zachowany
szyfrogram
szyfrogram
(inaczej: kryptogram, tekst tajny) wiadomość, która została zaszyfrowana (lub jeszcze nie została odszyfrowana)
tekst jawny
tekst jawny
(inaczej: tekst otwarty) wiadomość, która nie została jeszcze zaszyfrowana (lub została odszyfrowana)