Lekcja 23. Algorytmy szyfrowania i tekstowe (szyfr Cezara, GADERYPOLUKI)
ŚredniPo co się tego uczymy?
Podstawa programowa (INF.04.3.3) wymienia wprost "algorytmy tekstowe" i "algorytmy szyfrowania" jako coś, co trzeba umieć zaimplementować. To też świetny sposób na przećwiczenie pracy z tekstem (string) w C# — indeksowanie znaków, kody ASCII, pętle po znakach — czyli umiejętności przydatne w każdym programie przetwarzającym dane od użytkownika.
Teoria
Szyfr Cezara to jeden z najstarszych i najprostszych szyfrów podstawieniowych — każda litera tekstu jawnego jest zastępowana literą przesuniętą o stałą liczbę pozycji w alfabecie (tzw. klucz). Przy przesunięciu 3: A→D, B→E, C→F, itd. Po dotarciu do końca alfabetu przesunięcie "zawija się" na początek (X→A, Y→B, Z→C). Do deszyfrowania wystarczy przesunąć litery w przeciwną stronę o tę samą wartość.
GADERYPOLUKI to polski szyfr podstawieniowy, w którym litery alfabetu są zamieniane parami zgodnie ze słowem-kluczem GADERYPOLUKI: G↔A, D↔E, R↔Y, P↔O, L↔U, K↔I (litery łączone są w pary wg kolejności liter w tym słowie). Zasada działania jest identyczna jak w prostym szyfrze podstawieniowym — tylko reguła zamiany jest inna niż stałe przesunięcie.
W C# do pracy z pojedynczymi znakami tekstu przydają się: indeksowanie tekst[i] (dostęp do konkretnego znaku), typ char oraz fakt, że w C# znaki mają swoje kody liczbowe (ASCII/Unicode) — można je konwertować na liczby i z powrotem, co jest kluczowe przy przesuwaniu liter w szyfrze Cezara.
Schemat
Szyfr Cezara z przesunięciem 3:
Alfabet jawny: A B C D E F G H I J K ...
Alfabet zaszyfr.: D E F G H I J K L M N ...
(każda litera przesunięta o 3 miejsca w prawo)
Szyfrowanie "KOT":
K -> N
O -> R
T -> W
Wynik: "NRW"
Deszyfrowanie: przesuwamy w drugą stronę (o 3 w lewo): N->K, R->O, W->T
Przykład z życia
Szyfr Cezara i podobne proste szyfry podstawieniowe nie są dziś używane do prawdziwego zabezpieczania danych (łamie się je w kilka sekund), ale sama IDEA podstawienia znaków leży u podstaw dużo poważniejszych systemów szyfrowania (np. AES, którego używa HTTPS przy każdym wejściu na stronę bankową). Zrozumienie prostego przypadku pomaga zrozumieć, na czym w ogóle polega szyfrowanie — zamiana czytelnej informacji na nieczytelną według znanego obu stronom klucza/reguły.
Kod (C#)
using System;
using System.Text;
class Program
{
// Szyfr Cezara — działa tylko na wielkich literach A-Z dla uproszczenia.
static string SzyfrCezara(string tekst, int przesuniecie)
{
var wynik = new StringBuilder();
foreach (char znak in tekst)
{
if (znak >= 'A' && znak <= 'Z')
{
// 'A' ma kod 65. Odejmujemy go, żeby dostać pozycję 0-25,
// dodajemy przesunięcie, bierzemy resztę z dzielenia przez 26
// (żeby "zawinąć" po Z z powrotem na A), i wracamy do litery.
int pozycja = (znak - 'A' + przesuniecie) % 26;
wynik.Append((char)('A' + pozycja));
}
else
{
wynik.Append(znak); // spacje i inne znaki bez zmian
}
}
return wynik.ToString();
}
static void Main()
{
string tajneSlowo = "PROGRAMOWANIE";
string zaszyfrowane = SzyfrCezara(tajneSlowo, 3);
string odszyfrowane = SzyfrCezara(zaszyfrowane, 26 - 3); // przesunięcie w drugą stronę
Console.WriteLine($"Tekst jawny: {tajneSlowo}");
Console.WriteLine($"Zaszyfrowany: {zaszyfrowane}");
Console.WriteLine($"Odszyfrowany: {odszyfrowane}");
}
}
Komentarz i wyjaśnienie kodu
Najważniejsza linijka to (znak - 'A' + przesuniecie) % 26. Odejmowanie znaków w C# (znak - 'A') daje liczbę — różnicę ich kodów. Dla litery A da to 0, dla B da 1, itd. Po dodaniu przesunięcia bierzemy resztę z dzielenia przez 26 (liczba liter w alfabecie łacińskim), żeby po przekroczeniu Z "zawinąć" z powrotem na A. Na końcu (char)('A' + pozycja) zamienia tę liczbę z powrotem na literę. Deszyfrowanie to po prostu przesunięcie w drugą stronę — a przesunięcie "w drugą stronę o 3" to to samo co "do przodu o 26-3=23", dzięki czemu można użyć tej samej funkcji.
Ćwiczenie samodzielne
Zmień przesunięcie na inną wartość (np. 7 albo 13 — słynne ROT13) i sprawdź, czy szyfrowanie i deszyfrowanie nadal działają poprawnie dla tego samego tekstu.
Plac zabaw — wypróbuj online
Poniższy kod wykonuje się od razu w Twojej przeglądarce — nic nie trzeba instalować. Zmień kod i kliknij „Uruchom”.
Zadania do pracy własnej
Rozszerz funkcję
SzyfrCezara, żeby działała też dla małych liter (a-z), nie tylko wielkich.Napisz funkcję realizującą szyfr GADERYPOLUKI dla wielkich liter G, A, D, E, R, Y, P, O, L, U, K, I (pozostałe litery alfabetu zostają bez zmian). Podpowiedź: zbuduj słownik (Dictionary<char, char>) z parami zamian.
Napisz program łamiący prosty szyfr Cezara metodą "brute force" — wypróbuj wszystkie 26 możliwych przesunięć na zaszyfrowanym tekście i wypisz wszystkie warianty, żeby użytkownik sam wybrał ten, który ma sens.
Typowe błędy
Zapominanie o "zawijaniu" alfabetu — bez operatora % (reszta z dzielenia) litera Z przesunięta o 3 dałaby znak spoza alfabetu zamiast wrócić na C.
Szyfrowanie znaków spoza zakresu A-Z — bez sprawdzenia if (znak >= 'A' && znak <= 'Z') spacje, cyfry i polskie znaki (ą, ę, ć) też zostałyby "przesunięte" i zmieniłyby się w bezsensowne symbole.
Mylenie kierunku przesunięcia przy deszyfrowaniu — trzeba pamiętać, że deszyfrowanie to przesunięcie o tę samą wartość, ale w przeciwnym kierunku.
Nawiązanie do egzaminu zawodowego
To bezpośrednia realizacja INF.04.3.3 — "algorytmy tekstowe, szyfrowania". Ten sam mechanizm indeksowania znaków i pracy z kodami liter przyda się też przy innych zadaniach tekstowych z arkuszy egzaminacyjnych (np. zliczanie wystąpień liter, sprawdzanie czy tekst jest palindromem, walidacja formatu wprowadzonych danych).