Strona główna » Algorytmy » Szyfry » Szyfr Sylabiki
 

Szyfr Sylabiki

O szyfrze

Szyfr Sylabiki potrzebuje klucza do szyfrowania. Taki klucz dzieli się na sylaby, które z kolei tworzą pary liter, dlatego bardzo ważne jest, aby długość klucza była parzysta. Co więcej w kluczu każdy znak powinien wystąpić najwyżej raz. Podczas szyfrowania tekstu sprawdzamy czy sprawdzany znak tekstu jawnego występuje w którejś z par. Jeśli tak to daną literę zamieniamy na powiązaną z nią, a jeśli nie to przepisujemy literkę bez zmian.

Szyfrowanie

Przykładowo weźmy najbardziej znany klucz: GADERYPOLUKI. W celu uproszczenia kodowania zapiszmy go dzieląc klucz na sylaby: GA-DE-RY-PO-LU-KI. Jednak taki sposób nie jest dla wszystkich przejrzysty, dlatego drugim polecanym sposobem jest zapisanie klucza w tabelce. Tabelkę tworzymy zapisując litery kolejnych sylab jedna pod drugą:

ZGDRPLK
naAEYOUI

Teraz chcąc zaszyfrować słowo DRUH szukamy kolejno w tabelce: D i zamieniamy na E, R zamieniamy na Y, U na L - warto zauważyć, że nieważne w którym wierszu zapisane jest litera, bo i tak zamieniamy na drugą literę z tej samej kolumny. Ostatnią literą do zaszyfrowania jest H, które nie występuje w kluczu, więc przepisujemy literę bez zmian. Zapisując kolejne litery koło siebie otrzymujemy tekst zaszyfrowany: EYLH.

Deszyfrowanie

W przypadku deszyfrowania wykonujemy dokładnie te same operacje co podczas szyfrowania. Czyli w celu rozszyfrowania powyższego przykładu wystarczyłoby zaszyfrować go z kluczem AGEDYROPULIK.

Implementacja

Zadanie

Napisz program, który na wejściu wczyta dwie linijki tekstu. Pierwsza będzie zawierała klucz, a druga tekst do zaszyfrowania. Na wyjście powinien zostać wypisany tekst zaszyfrowany zgodnie z szyfrem Literówka przy użyciu wczytanego klucza. Przed szyfrowaniem program musi sprawdzić czy długość klucza jest prawidłowa. Jeśli nie to powinien zwrócić sam znak końca linii. Przykładowo dla wejścia:

  1. GADERYPOLUKI
  2. DRUH

otrzymamy:

  1. EYLH

Funkcja pomocnicza

W wczytanym kodzie będziemy potrzebowali znaleźć konkretny znak, dlatego napiszemy funkcje findChar(), która przyjmie dwa argumenty tekst do przeszukania oraz znak do znalezienia. Funkcja jeśli znajdzie znak w tekście zwróci jego pozycję, a jeśli nie to wartość -1.

  1. int findChar(const char* kod, char look){
  2.   for(int i = 0; kod[i]; i++)
  3.     if(kod[i] == look)
  4.       return i;
  5.   return -1;
  6. }

(2.) Dla każdego znaku w tekście (3.) funkcja sprawdza czy jest szukanym znakiem. Jeśli tak to (4.) zwracam na której leży pozycję. Jednak jeśli pętla (2.) się zakończy (natrafi na znak \0) to znaczy, że znak nie występuje w tekście czyli wtedy (5.) zwraca -1.

Szyfrowanie i deszyfrowanie

W opisie szyfru wspomniałem, że deszyfrowanie odbywa się poprzez ponowne szyfrowanie co można udowodnić faktem, że kolejne znaki zamieniamy w parach.

  1. char* change(const char* kod, const char* txt){
  2.   int dl = (strlen(kod) % 2 == 0) ? strlen(txt) : 0;
  3.   char* wynik = new char[dl];
  4.   for(int i = 0; i < dl; i++){
  5.     int t = findChar(kod, txt[i]);
  6.     wynik[i] = (t == -1) ? txt[i] : kod[(t % 2 == 0) ? (t + 1) : (t - 1)];
  7.   }
  8.   wynik[dl] = '\0';
  9.   return wynik;
  10. }

(2.) Ustalamy jakiej długości będzie tekst wynikowy. Tutaj też sprawdzamy czy kod potrzebny do szyfrowania jest prawidłowy, ponieważ sprawdzamy czy klucz jest parzystej długości. Jeśli jest to ustalamy długość tekstu wynikowego na długość tekstu jawnego (bądź zaszyfrowanego). Jeśli nie to długość będzie 0 czyli dopiszemy sam znak końca linii. (2.) Alokujemy pamięć pod tekst wynikowy. (4.) Dla każdego znaku w tekście (5.) szukamy jego pozycji i zapisujemy do tymczasowej zmiennej t. (6.) Szyfrowanie znaku odbywa się dwuetapowo: jeśli pozycja wynosi -1 to sytuacja jest prosta: przepisujemy i-ty znak z podanego tekstu. Jednak, gdy pozycja jest > -1 to sprawdzamy czy pozycja jest parzysta czy nieparzysta, ponieważ jeśli pozycja jest parzysta to litera powiązana w parze jest po prawej stronie. Dla znaków na pozycji nieparzystej sytuacja jest analogiczna. (8.) Na sam koniec dopisujemy znak końca linii i (9.) zwracamy wynik.

Testowanie funkcji

Poniższa funkcja main() pozwala przetestować napisany powyżej kod:

  1. int main () {
  2.   char* kod = new char[128];
  3.   cin.getline(kod, 128);
  4.   char* txt = new char[128];
  5.   cin.getline(txt, 128);
  6.   char* txtc = change(kod, txt);
  7.   cout << txtc << endl;
  8.   char* txtd = change(kod, txtc);
  9.   cout << txtd << endl;
  10.   delete[] kod, txt, txtc, txtd;
  11.   system("pause");
  12.   return 0;
  13. }

Zadania

Zadanie 1

Zmodyfikuj funkcję, aby tekst był zaszyfrowany przy pomocy wprowadzonego klucza oraz klucza powstałego poprzez zamianę dużych liter w kluczu na małe oraz małych na duże. Spróbuj napisać kod, aby funkcję change() wywołać tylko raz z oryginalnym kluczem.

Przykładowo dla danych:

  1. GADERYPOLUKI
  2. Druh
otrzymujemy:
  1. Eylh

Zadanie 2

Linijki (4. - 6.) funkcji change() zapisz jako dwie linijki.