
Szyfr Cezara
Szyfrowanie podstawieniowe to najprostsza klasa technik kryptograficznych, w których każda litera tekstu jawnego jest zastępowana inną literą według ustalonej reguły. Mechanizm jest deterministyczny, łatwy do implementacji i zrozumienia, a jednocześnie dobrze pokazuje podstawowe pojęcia kryptografii: klucz, przestrzeń kluczy, operacje na alfabetach i podatność na ataki analityczne. Historycznie wykorzystywano go do ochrony krótkich komunikatów, dziś pełni głównie rolę dydaktyczną i wprowadza do myślenia o szyfrach klasycznych, gdzie transformacja danych odbywa się na poziomie symboli, a nie bitów, czego przykładem jest Szyfr Cezara.
Spis Treści
Szyfr Cezara jako przykład szyfru podstawieniowego z przesunięciem cyklicznym i ograniczeniami wynikającymi z małej przestrzeni kluczy
Szyfr polega na przesunięciu każdej litery alfabetu o stałą liczbę pozycji. Jeśli alfabet ma rozmiar N, to operacja odbywa się modulo N. Dla alfabetu łacińskiego bez znaków diakrytycznych N=26. Klucz to liczba całkowita k, gdzie 0≤k<N.
Mechanizm:
- każdej literze przypisuje się indeks (A=0, B=1, …, Z=25)
- szyfrowanie: c=(p+k)modN
- deszyfrowanie: p=(c−k)modN
To przesunięcie jest cykliczne, więc po Z wracamy do A. W praktyce oznacza to, że tekst „ABC” przy kluczu k=3 daje „DEF”.
Wzór matematyczny i przykład obliczeniowy
| Element | Zapis |
|---|---|
| Szyfrowanie | c=(p+k)mod26 |
| Deszyfrowanie | p=(c−k)mod26 |
| Przykład | p=2(C),k=3⇒c=(2+3)mod26=5(F) |
Istotna właściwość: przestrzeń kluczy ma tylko 26 możliwych wartości. To oznacza, że atak brute-force jest trywialny – można sprawdzić wszystkie możliwości w czasie stałym.
Implementacja algorytmu Szyfr Cezara w językach C, C++ i Python z uwzględnieniem operacji na kodach znaków ASCII
Implementacja opiera się na pracy na kodach ASCII. Litery 'A’–’Z’ i 'a’–’z’ mają różne zakresy, więc trzeba je traktować osobno.
C
| Kod |
|---|
| „`c |
| #include <stdio.h> |
| char encrypt(char c, int k) { |
| if (c >= 'A’ && c <= 'Z’) |
| return (c – 'A’ + k) % 26 + 'A’; |
| if (c >= 'a’ && c <= 'z’) |
| return (c – 'a’ + k) % 26 + 'a’; |
| return c; |
| } |
| int main() { |
| char text[] = „Hello”; |
| int k = 3; |
| for (int i = 0; text[i]; i++) |
| text[i] = encrypt(text[i], k); |
| printf(„%s\n”, text); |
| return 0; |
| } |
| „` |
C++
| Kod |
|---|
| „`cpp |
| #include <iostream> |
| using namespace std; |
| char encrypt(char c, int k) { |
| if (isupper(c)) |
| return (c – 'A’ + k) % 26 + 'A’; |
| if (islower(c)) |
| return (c – 'a’ + k) % 26 + 'a’; |
| return c; |
| } |
| int main() { |
| string text = „Hello”; |
| int k = 3; |
| for (char &c : text) |
| c = encrypt(c, k); |
| cout << text << endl; |
| } |
| „` |
Python
| Kod |
|---|
| „`python |
| def encrypt(text, k): |
| result = „” |
| for c in text: |
| if c.isupper(): |
| result += chr((ord(c) – 65 + k) % 26 + 65) |
| elif c.islower(): |
| result += chr((ord(c) – 97 + k) % 26 + 97) |
| else: |
| result += c |
| return result |
| print(encrypt(„Hello”, 3)) |
| „` |
Każda implementacja robi dokładnie to samo: przelicza znak na indeks, dodaje przesunięcie i wraca do znaku.
Analiza bezpieczeństwa Szyfr Cezara z perspektywy kryptografii klasycznej i praktycznych metod łamania
Szyfr nie zapewnia realnego bezpieczeństwa. Powody:
- Mała przestrzeń kluczy (26 możliwości)
- Zachowanie struktury języka (częstotliwość liter nie znika)
- Brak dyfuzji i konfuzji (pojęcia z teorii Shannona)
Atak brute-force
Sprawdzenie wszystkich możliwych kluczy:
| Kod |
|---|
| „`python |
| def brute_force(text): |
| for k in range(26): |
| print(k, encrypt(text, -k)) |
| „` |
Wynik daje wszystkie możliwe odszyfrowania – człowiek rozpoznaje poprawny tekst.
Analiza częstotliwości
Najczęstsze litery w języku polskim i angielskim:
- E, A, O, I
Jeśli w szyfrogramie najczęściej występuje np. litera X, można przypuszczać, że odpowiada ona literze E.
Proces:
- policz częstości
- dopasuj przesunięcie
- zweryfikuj ręcznie
To działa szczególnie dobrze dla długich tekstów.
Rozszerzenia i warianty Szyfr Cezara stosowane w praktyce dydaktycznej oraz ich ograniczenia
ROT13
Specjalny przypadek, gdzie k=13
| Wzór |
|---|
| c=(p+13)mod26 |
Cechy:
- szyfrowanie = deszyfrowanie
- stosowany do maskowania tekstu (np. spoilery)
Alfabet rozszerzony
Można użyć:
- polskich znaków (ą, ć, ę…)
- cyfr
- znaków specjalnych
Problem: trzeba jawnie zdefiniować alfabet i jego kolejność.
Szyfr z kluczem tekstowym
Zamiast liczby:
- klucz = słowo
- każda litera daje przesunięcie
To prowadzi do szyfru Vigenère’a.
Uwagi praktyczne wynikające z implementacji i typowych błędów początkujących
- błąd z modulo dla liczb ujemnych (w C/C++ trzeba uważać)
- nieuwzględnienie małych/dużych liter
- ignorowanie znaków spoza alfabetu
- mieszanie kodowania znaków (UTF-8 vs ASCII)
- błędne założenie, że to „bezpieczne szyfrowanie”
Częsty problem: ktoś używa tego szyfru do „ukrycia hasła” w aplikacji. To daje fałszywe poczucie bezpieczeństwa – odszyfrowanie zajmuje sekundy.
FAQ
Czy Szyfr Cezara jest bezpieczny?
Nie. Można go złamać natychmiast brute-force lub analizą częstotliwości.
Ile jest możliwych kluczy?
Dla alfabetu 26-literowego dokładnie 26.
Czy można go używać w realnych systemach?
Nie. Wyłącznie do nauki lub jako ciekawostka.
Dlaczego działa modulo 26?
Bo alfabet ma 26 liter i operacja musi być cykliczna.
Czy działa dla języka polskiego?
Tak, ale trzeba zdefiniować większy alfabet (np. 32 znaki).
Czy ROT13 to to samo?
To specjalny przypadek tego szyfru z przesunięciem 13.
Jak szybko można go złamać?
W praktyce natychmiast – poniżej 1 sekundy nawet ręcznie.
Czy szyfr zmienia długość tekstu?
Nie. Każdy znak zamieniany jest na jeden znak.
Źródło Foto: Freepik


