Szyfr Cezara
Szyfr Cezara to jeden z najprostszych szyfrów w historii kryptografii.
Legenda mówi, że używał go Juliusz Cezar, aby wysyłać tajne wiadomości do swoich dowódców.
Zasada jest bardzo prosta:
mamy alfabet, np.
ABCDEFGHIJKLMNOPQRSTUVWXYZwybieramy przesunięcie, np. o 3 litery
każdą literę zastępujemy literą oddaloną o 3 pozycje w prawo
Przykład (przesunięcie o 3):
A → D
B → E
C → F
X → A
Y → B
Z → C
Słowo ALA po zaszyfrowaniu może wyglądać np. tak: DOD.
To oznacza, że każda litera w tekście jawnym jest zamieniana na inną literę według prostego, powtarzalnego wzoru (przesunięcie w alfabecie).
Ten typ szyfrowania nazywamy monoalfabetycznym szyfrem podstawieniowym – każda litera ma zawsze tę samą „zaszyfrowaną odpowiedniczkę”.
2. Jak to się ma do naszego programu?
Twój program nie realizuje dokładnie „klasycznego” przesunięcia o 3 litery, ale robi coś bardzo podobnego:
mamy alfabet1 – litery, które wolno wpisywać
mamy alfabet2 – znaki szyfrujące, które odpowiadają tym literom
każdą literę z
name(podany tekst) zamieniasz na inny znak zalfabet2na tej samej pozycji.
Czyli:
zamiast „przesuwać literę o kilka miejsc w alfabecie”,
Ty mapujesz litery z jednego „alfabetu” na drugi.
To nadal jest szyfr podstawieniowy – idea ta sama:
Znak jawny → zawsze ten sam znak zaszyfrowany.
Możesz uczniom powiedzieć tak:
„Klasyczny szyfr Cezara przesuwa litery o kilka miejsc, a nasz program robi podobną rzecz, tylko zamiast przesuwania używa gotowej tabelki zamian (alfabet1 → alfabet2).”
3. Kod programu – przegląd
Twój kod:
#include <iostream>
#include <string>
int main()
{
std::string name,szyfr;
int nr = 0;
std::string alfabet1 = "abcdefghijklmnoprstuw";
std::string alfabet2 = "1234567890!@#$%^&*()Q";
std::cout << "Tekst do zaszyfrowania? \n";
getline (std::cin, name);
for(int i =0; i< name.size();i++) {
nr = alfabet1.find(name[i]);
szyfr += alfabet2[nr];
}
std::cout << szyfr;
}
Spróbujmy go rozbić na kawałki i przy okazji podpiąć pod Twoje pytania.
4. Nagłówki – dlaczego są potrzebne?
#include <iostream>
#include <string>
#include <iostream>– udostępnia strumienie wejścia/wyjścia, m.in.std::cout– wypisywanie na ekranstd::cin– wczytywanie z klawiatury
#include <string>– udostępnia typstd::string, czyli:ciąg znaków (tekst),
na którym mamy metody typu
size(),find(),at(), itp.
To łączy się z Twoimi pytaniami:
„Tekst to jaki typ zmiennej?” – w tym programie to właśnie std::string.
5. Funkcja main i deklaracja zmiennych
int main()
{
std::string name,szyfr;
int nr = 0;
std::string alfabet1 = "abcdefghijklmnoprstuw";
std::string alfabet2 = "1234567890!@#$%^&*()Q";
...
}
int main()– główna funkcja programu. Tutaj wszystko się zaczyna.std::string name, szyfr;name– tekst, który użytkownik wpisze z klawiatury,szyfr– wynik zaszyfrowania (początkowo pusty string).
Na pytanie: „Jakie wartości może przyjmować string?” –std::string może przechowywać dowolny ciąg znaków, np. "Ala", "test123", "ala ma kota", nawet pusty tekst "".
int nr = 0;nrto zmienna typuint– przechowuje numer pozycji litery w alfabecie (index walfabet1).
std::string alfabet1 = "abcdefghijklmnoprstuw";to „zwykły” alfabet, ale uproszczony (bez wszystkich liter, np. bez „q”, „y”, „z”).
std::string alfabet2 = "1234567890!@#$%^&*()Q";alfabet szyfrujący – każdy znak ma indeks odpowiadający literze w
alfabet1.
Czyli:
alfabet1[0]→alfabet2[0]alfabet1[1]→alfabet2[1]itd.
To jest Twoja tabelka podstawień – odpowiednik „przesunięcia” w szyfrze Cezara.
6. Wczytywanie tekstu – getline(std::cin, name);
std::cout << "Tekst do zaszyfrowania? \n";
getline (std::cin, name);
std::cout << "Tekst do zaszyfrowania? \n";wypisuje pytanie na ekran,
\n– znak nowej linii.
getline(std::cin, name);wczytuje całą linię tekstu (aż do naciśnięcia ENTER),
zapisuje ją do zmiennej
name.
To jest odpowiedź na Twoje pytanie:
„Co znaczy getline (std::cin, name);?”
Wczytaj cały wiersz tekstu z klawiatury (łącznie ze spacjami) i zapisz go jako string w zmiennej
name.
Różnica do std::cin >> name; jest taka, że cin >> zatrzymuje się na pierwszej spacji, a getline bierze wszystko do końca linii.
7. Pętla for i name.size()
for(int i =0; i< name.size();i++) {
nr = alfabet1.find(name[i]);
szyfr += alfabet2[nr];
}
7.1. Nagłówek pętli
for(int i = 0; i < name.size(); i++)
int i = 0;– zmienna sterująca pętlą, startuje od 0.i < name.size();– warunek kontynuowania:name.size()zwraca długość stringa (liczbę znaków),jeśli
namema np. 5 znaków,name.size()= 5,indeksy znaków to: 0,1,2,3,4,
dlatego warunek jest
i < size(), a nie<=.
To odpowiada na pytanie:
„name.size() co otrzymamy?”
name.size()zwraca liczbę znaków w stringuname(typustd::size_t, ale w praktyce traktujemy to jak liczbę całkowitą).
Przykłady:
name = "ala"→name.size() == 3name = ""→name.size() == 0
7.2. name[i] – pojedynczy znak
W środku pętli używasz:
name[i]
name[i]oznacza i-ty znak w stringu,przy
i = 0– pierwszy znak,przy
i = 1– drugi znak itd.
8. Szukanie znaku w alfabecie – alfabet1.find(name[i])
nr = alfabet1.find(name[i]);
To jest kluczowa linijka dla szyfrowania.
alfabet1.find(name[i])szuka znakuname[i]w stringualfabet1.Jeśli znajdzie, zwraca numer pozycji (indeks) tego znaku.
Ten numer zapisujemy do zmiennej
nr.
Możesz to tłumaczyć uczniom tak:
alfabet1.find(name[i])mówi nam: „którą literą w alfabecie jest aktualny znak?”.
To dokładnie Twoje pytanie:
„zwraca która litera jest w alfabecie alfabet1.find(name[i])” – TAK, właśnie to robi.
Przykład, jeśli:
std::string alfabet1 = "abcdefghijklmnoprstuw";
alfabet1.find('a')→ 0alfabet1.find('b')→ 1alfabet1.find('c')→ 2
Jeśli znak nie istnieje w alfabet1, metoda find() zwróci specjalną wartość std::string::npos (bardzo dużą liczbę).
W Twoim kodzie zakładamy, że użytkownik wpisuje tylko litery znajdujące się w alfabet1.
9. Budowanie zaszyfrowanego tekstu – szyfr += alfabet2[nr];
szyfr += alfabet2[nr];
alfabet2[nr]– bierzemy znak zalfabet2o tym samym indeksie, który znaleźliśmy walfabet1.szyfr += ...– dopisujemy ten znak na koniec stringaszyfr.
To oznacza:
„Zamień literę z
alfabet1na odpowiadający jej znak zalfabet2i dołóż do końca zaszyfrowanego tekstu”.
Przykład:
alfabet1 = "abc..."
alfabet2 = "123..."
name = "ab"
Iteracje:
dla
i = 0→name[0] = 'a'alfabet1.find('a')→ 0alfabet2[0]→ '1′szyfr = "1"
dla
i = 1→name[1] = 'b'alfabet1.find('b')→ 1alfabet2[1]→ '2′szyfr = "12"
Na końcu:
std::cout << szyfr;
wypisze zaszyfrowany tekst.
10. Połączenie z szyfrem Cezara
Klasyczny szyfr Cezara:
alfabet:
ABCDEFGHIJKLMNOPQRSTUVWXYZprzesunięcie: np. o 3 w prawo
każda litera ma zaszyfrowaną odpowiedniczkę na podstawie przesunięcia
Twój program:
ma
alfabet1ialfabet2,każda litera z
alfabet1ma stałą odpowiedniczkę walfabet2,zamiast przesuwać, korzystasz z „tabelki zamian”.
Możesz powiedzieć uczniom:
Nasz kod realizuje szyfr podstawieniowy taki jak Cezara, tylko zamiast przesunięcia o 3 litery mamy ręcznie przygotowane odpowiadające sobie znaki w dwóch stringach.
Chcesz klasycznego Cezara w tej samej konwencji?
Możesz ustawić:
std::string alfabet1 = "abcdefghijklmnopqrstuvwxyz";
std::string alfabet2 = "defghijklmnopqrstuvwxyzabc"; // przesunięcie o 3
I reszta programu będzie działać tak samo – to już będzie „prawie podręcznikowy” szyfr Cezara.
11. Pytania kontrolne do tego artykułu
Na koniec możesz wykorzystać część z Twoich 60 pytań – tu masz mały pakiet „pod lekcję”:
60 pytań – szyfr Cezara i kod w C++
Jakie wartości może przyjmować zmienna typu
std::stringw C++?„Tekst” w tym programie jest przechowywany w jakim typie zmiennej?
Co oznacza instrukcja
std::string imie = "olek";?Po co w programie jest dyrektywa
#include <string>?Do czego służy
#include <iostream>w tym kodzie?Co robi instrukcja
std::cout << "Tekst do zaszyfrowania? \n";?Co znaczy wywołanie
getline(std::cin, name);w programie?Czym różni się
getline(std::cin, name)odstd::cin >> name;?Jakiego typu są zmienne
nameiszyfrw podanym kodzie?Jaką wartość początkową ma zmienna
szyfrpo uruchomieniu programu?Co przechowuje zmienna
alfabet1?Co przechowuje zmienna
alfabet2?Dlaczego w programie używane są dwa różne „alfabety”:
alfabet1ialfabet2?Co oznacza, że
std::stringjest typem złożonym (klasą), a nie prostym typem jakint?Co oznacza
stdw zapisiestd::stringistd::cout?Jak można uprościć zapis
std::stringużywającusing namespace std;?Jakie podstawowe operacje można wykonywać na zmiennej typu
std::string(wymień przykłady)?Co oznacza nagłówek pętli
for(int i = 0; i < name.size(); i++)?Co oznacza zapis
i++w pętlifor?Jakiego typu jest wartość zwracana przez
name.size()?Co otrzymamy z wyrażenia
name.size()dla tekstu"ala"?Dlaczego w warunku pętli użyto
i < name.size(), a niei <= name.size()?Co oznacza zapis
name[i]wewnątrz pętli?Co to znaczy, że
namejest indeksowany od zera?Jakie indeksy mają znaki w stringu
"abc"?Co robi instrukcja
nr = alfabet1.find(name[i]);?Co dokładnie zwraca
alfabet1.find(name[i]), gdy znak istnieje walfabet1?Co zwróci
alfabet1.find(name[i]), gdy znak NIE występuje walfabet1?Jaką rolę pełni zmienna
nrw programie?Co robi instrukcja
szyfr += alfabet2[nr];?Co oznacza operator
+=w kontekście typustd::string?Jak sprawdzić długość łańcucha
alfabet1w programie?Dlaczego długość
alfabet1ialfabet2powinna być taka sama?Co się stanie, jeśli
name[i]będzie spacją, a walfabet1nie ma spacji?Jak można zabezpieczyć program przed sytuacją, gdy
alfabet1.find(name[i])nic nie znajdzie?Czy program poprawnie zaszyfruje wielkie litery (np.
A,B)? Uzasadnij.Jak można zmodyfikować program, aby ignorował wielkość liter (małe/wielkie)?
Jak można zmodynić program, aby znaki, których nie ma w
alfabet1, przepisywał bez szyfrowania?W jaki sposób można wypisać również oryginalny tekst obok zaszyfrowanego?
Co się stanie z wynikiem szyfrowania, jeśli zmienisz kolejność znaków w
alfabet1?Co się stanie z wynikiem szyfrowania, jeśli zmienisz kolejność znaków w
alfabet2?Co krok po kroku robi funkcja
std::getline, gdy użytkownik wpisuje tekst i naciska ENTER?Jak można sprawdzić w programie, czy zmienna
namejest pusta (nie zawiera znaków)?Jak można policzyć, ile znaków ma zaszyfrowany tekst zapisany w zmiennej
szyfr?Czym różni się użycie
name[i]odname.at(i)?Co robiłaby instrukcja
return 0;na końcu funkcjimain()?Co to znaczy, że string jest sekwencją znaków ułożonych „jeden po drugim” w pamięci?
W jaki sposób można na podstawie tego programu zrealizować operację „deszyfrowania” (powrotu z
szyfrdo zwykłego tekstu)?Czy zmienna typu
std::stringmoże przechowywać polskie znaki (ą, ę, ł, ś itd.)? Omów to krótko.Co to jest szyfr Cezara w teorii kryptografii?
Na czym polega klasyczny mechanizm szyfru Cezara (co robimy z literami)?
Czym szyfr Cezara różni się od ogólnego „szyfru podstawieniowego”?
W jaki sposób podany program realizuje ideę szyfru Cezara lub szyfru podstawieniowego?
Jak można zmodyfikować program tak, aby użyć klasycznego przesunięcia o 3 litery (typowy szyfr Cezara)?
Jak możemy opisać rolę „indeksu litery w alfabecie” w szyfrowaniu Cezara?
Dlaczego szyfr Cezara nie jest bezpieczny we współczesnej kryptografii?
Jak można zmienić program, aby użytkownik sam podawał wartość przesunięcia (np. o ile liter szyfrować)?
Jakie są zalety używania typu
std::stringprzy implementacji szyfru, zamiast tablicychar[]?W jaki sposób można wykorzystać ten program jako przykład na lekcji o podstawach kryptografii?
Dlaczego szyfrowanie typu Cezara (i Twój program) nazywamy szyfrowaniem przez podstawienie jednej litery inną literą?
Sprawdź, co pamiętasz
Pytania kontrolne
1. Jaki jest główny temat artykułu „Szyfr Cezara”?
Wskazówka: Odpowiedz własnymi słowami i wskaż najważniejszy cel lub problem opisany w materiale.
2. Które trzy pojęcia, zasady albo etapy z artykułu warto zapamiętać?
Wskazówka: Wybierz informacje potrzebne do wykonania zadania lub wyjaśnienia tematu innej osobie.
3. Jak można wykorzystać tę wiedzę w praktyce?
Wskazówka: Podaj konkretny przykład z lekcji, pracy przy komputerze albo codziennej sytuacji.
4. Jakie kroki należy wykonać, aby poprawnie zrealizować opisane zadanie?
Wskazówka: Ułóż najważniejsze czynności we właściwej kolejności.
5. Jakich narzędzi, funkcji lub materiałów potrzeba do wykonania zadania?
Wskazówka: Wymień elementy wskazane w artykule i krótko opisz ich rolę.
6. Która zasada opisana w artykule jest najważniejsza i dlaczego?
Wskazówka: Uzasadnij wybór przykładem z materiału.
7. Jaki błąd można popełnić podczas wykonywania zadania i jak go uniknąć?
Wskazówka: Wskaż możliwą trudność oraz sposób jej rozwiązania.
8. Jak wyjaśnisz ten temat osobie, która poznaje go po raz pierwszy?
Wskazówka: Użyj prostych słów i najważniejszych pojęć z artykułu.
9. Co zmieniłoby się, gdyby pominąć jeden z opisanych etapów lub zasad?
Wskazówka: Przewidź skutek i uzasadnij odpowiedź.
10. Jakie własne ćwiczenie lub przykład można przygotować na podstawie artykułu?
Wskazówka: Zaproponuj zadanie, które sprawdza zrozumienie materiału.
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.