Strona główna » Algorytmy » Artykuły » Szyfr AtBash

Szyfr AtBash

Wstęp

Szyfr AtBash jest monoalfabetycznym szyfrem przestawieniowym co oznacza, że każdej literze alfabetu przypada dokładnie jedna litera alfabetu jawnego oraz, że tekst zaszyfrowany jest złożony z liter tekstu jawnego, ale w innej kolejności. Prawdopodobnie został opracowany około roku 500 p.n.e.

W Biblii występują wyrazy przekształcone tym szyfrem.

Algorytm szyfrowania

Działanie szyfru polega na zamianie litery leżącej w odległości x od początku alfabetu na literę leżącą w odległości X od jego końca. Sposób zamiany liter przedstawia poniższa tabelka:

Tekst jawnyABCDEFGHIJKLMNOPQRSTUVWXYZ
SzyfrogramZYXWVUTSRQPONMLKJIHGFEDCBA

Jeśli chcemy odszyfrować tekst to wystarczy go ponownie zaszyfrować.

Przykład

Szyfrując słowo ATBASH należy każdy znak oddzielnie znaleźć w tabelce i zamienić na odpowiadający mu znak. W tym przypadku, dla A to Z, T to G itd. Ostatecznie zaszyfrowane słowo ATBASH to ZGYZHS.

Implementacja

Zakładamy, że nasz funkcja może modyfikować tekst wprowadzony jako argument, więc nie będzie zwracać żadnych danych, a przyjmie tekst jako argument.

  1. void cipher(char* txt) {
  2.   for(int i = 0; txt[i]; i++){
  3.     if(txt[i] >= 'A' && txt[i] <= 'Z'){
  4.       txt[i] = ('Z' - (txt[i] - 'A'));
  5.     }
  6.   }
  7. }

(2.) Dopóki nie natrafimy na koniec napisu: (3.) Sprawdzamy czy sprawdzany znak jest dużą literą - jeśli tak to (4.) odpowiednio go zamieniamy. Obliczamy, który jest to znak w alfabecie i tę wartość odejmujemy od końca.

Testowanie funkcji

W celu przetestowania szyfrowania tekstu można skorzystać z poniższej funkcji main():

  1. int main () {
  2.   char* txt = new char[128];
  3.   cin.getline(txt, 128);
  4.   cipher(txt);
  5.   cout << "Zaszyfrowany tekst: " << txt << endl;
  6.   cipher(txt);
  7.   cout << "Odszyfrowany tekst: " << txt << endl;
  8.   system("pause");
  9.   return 0;
  10. }

Udoskonalenie kodu

Załóżmy teraz, że w szyfrowanym tekście małe i duże liter zamieniają się oddzielnie czyli a zamienia się z z, a A z Z. W celu osiągnięcia celu należy delikatnie zmienić funkcję cipher().

  1. void cipher(char* txt, int from, int to) {
  2.   for(int i = 0; txt[i]; i++){
  3.     if(txt[i] >= 'A' && txt[i] <= 'Z'){
  4.       txt[i] = ('Z' - (txt[i] - 'A'));
  5.     } else if(txt[i] >= 'a' && txt[i] <= 'z'){
  6.       txt[i] = ('z' - (txt[i] - 'a'));
  7.     }
  8.   }
  9. }

Różnica z poprzednim kodem polega na dodania drugie warunku jeśli znak nie jest dużą literą - (5.) sprawdzamy wtedy czy jest małą literą. Jeśli tak to zamieniamy go na tej samej zasadzie. Nową wersję kodu można przetestować przy pomocy poprzednich testów.

Duże i małe litery oraz cyfry

W celu dodanie zamiany cyfr w obrębie ich alfabetu czyli: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, gdzie 0 zamienia się na 9, a 1 na 8 wystarczy dodać dodatkową klauzulę else i upewnić się, że dany znak jest cyfrą. Ten przypadek jest dostępny w kodzie źródłowym B.

Jednak proponuje bardziej ogólne podejście do tematu: przekształćmy funkcję tak, aby alfabet użyty do szyfrowania można było ustalić podczas wywołania funkcji. Innymi słowy nasz funkcja cipher prócz argumentu z tekstem do zaszyfrowania otrzyma, który znak jest pierwszy w alfabecie, a który ostatni:

  1. void cipher(char* txt, int from, int to) {
  2.   for(int i = 0; txt[i]; i++)
  3.     if(txt[i] >= from && txt[i] <= to)
  4.       txt[i] = (to - (txt[i] - from));
  5. }

Wtedy, aby zaszyfrować małe i duże litery oraz cyfry należy wywołać funkcję cipher 3 razy:

  1.   cipher(txt, 'A', 'Z');
  2.   cipher(txt, 'a', 'z');
  3.   cipher(txt, '0', '9');

Szyfrujemy kolejno (1.) duże litery, (2.) małe litery oraz (3.) cyfry.

Zadania

Zadanie 1

Napisz funkcję cipherBracket(), która zamieni nawiasy w myśl szyfrowania AtBash czyli ( z ), [ z ], { z } oraz < z >

Zadanie 2

Zmodyfikuj Kod źródłowy Duże i małe litery oraz cyfry, aby: