Strona główna » Algorytmy » Szyfry » Szyfr Monome-Dinome
 

Szyfr Monome-Dinome

Wstęp

Szyfr Monome-Dinome to szyfr podstawieniowy, który w celu zaszyfrowania danych korzysta ze specjalnie przygotowanej tabeli o rozmiarach 3×8. Z tego powodu w alfabecie dwa znaki łacińskie muszą być połączone z innymi lub wykluczone z szyfrowania. Ostateczny szyfrogram składa się z samych cyfr.

Opis szyfrowania

Pierwszy etap podczas szyfrowania Monome-Dinome polega na przygotowaniu specjalnej tabelki 3×8. Tabelka powstaje poprzez wybranie słowa klucza, a następnie uzupełnienie wyrażenie do 24 liter poprzez dopisanie nie występujących w kluczu liter. Ze względu na ograniczenie do 24 znaków wyklucza się możliwość wpisywania liter J oraz X. Następny krok polega na wybraniu słowa klucz złożonego z 10 różnych cyfr. Następnie z takiego klucza liczbowego pierwsze osiem cyfr przepisujemy jako nagłówki kolumn tabeli, a pozostałe dwie cyfry jako nagłówki wierszy drugiego oraz trzeciego.

Mają przygotowaną tabelke można przejść do szyfrowania. Każdy szyfrowany znak należy znaleźć w tabelce i określić w której kolumnie oraz wierszu się znajduje. Jeśli znak znajduje się w pierwszym wierszu to znak jest szyfrowany jedynie poprzez nagłówek kolumny. W przeciwnym wypadku należy zaszyfrować przy pomocy nagłówku wiersza oraz nagłówku kolumny względem komórki gdzie dany znak się znajduje. Po zapisaniu wszystkich cyfr koło siebie otrzymujemy szyfrogram.

W celu odszyfrowania danych należy brać kolejne liczby. Jeśli dana cyfra jest nagłówkiem wiersza to oznacza, że litera została zaszyfrowana przez dwie kolejne cyfry. W przeciwnym wypadku została zaszyfrowana jednym znakiem, który oznacza, że należy z pierwszego wiersza wybrać wartość w kolumnie wskazaną przez cyfre.

Przykład

W pierwszym etapie należy utworzyć tabelke do szyfrowania. Przykładowa poprawna tabelka utworzona na podstawie słowa kluczowego HASLO oraz liczby 0195827346 wygląda następująco:

 01958273
-HASLOBCD
4EFGIKMNP
6QRTUVWYZ

Załóżmy, że będziemy szyfrować wyrażenie "SZYFROWANIE". Pierwsza litera S znajduje się w pierwszym wierszu, więc zostaje zaszyfrowana jedynie przez numer kolumny "9". Jednak litera Z znajduje się w trzecim wierszu, więc należy ją zaszyfrować nagłówkiem wiersza w którym się znajduje oraz nagłówkiem kolumny czyli "63". Kolejne litery są szyfrowane nastepuąco:

ZnakSZYFROWANIE
Szyfr9636741618621474540

Ostateczny szyfrogram to: 9636741618621474540.

Dodatkowe informacje

Jak można zauważyć każda litera jest zastępowana przez jedną lub dwie cyfry prowadzi do zwiększenia długości szyfrowanego tekstu dwukrotnie. Z tego powodu warto przeanalizować, które litery występują najczęściej. W ten sposób zostanie ograniczona ilość znaków potrzebna do przechowywania zaszyfrowanych znaków.

Implementacja

Przedstawiona implementacja poniżej szyfrje dane zgodnie z szyfrem Monome-Dinome. Pozwala ona na ustawienie dowolnego słowa klucza oraz klucz liczbowego. W programie zakłada się poprawność danych wejściowych oraz, że wszystkie dane są pisane jedynie wielkimi literami alfabetu łacińskiego bez znaków J oraz X.

Uzupełnianie klucza

W celu uzupełnienia klucza pozostałymi znakami alfabetu należy wyszukąc kolejne litery alfabetu w kluczu i jeśli nie można ich odnaleźć to dopisać je na koniec. Zamiast przechowywać dane w tabeli to będą one przechowywane w postaci 24 znakowego tekstu.

C++
C#
  1. string uzupelnijKlucz(string klucz) {
  2.   for (int i = 'A'; i <= 'Z'; i++) {
  3.     if (i != 'J' && i != 'X') {
  4.       size_t poz = klucz.find(i);
  5.       if (poz == string::npos) {
  6.         klucz += (char)(i);
  7.       }
  8.     }
  9.   }
  10.   return klucz;
  11. }

(2.) Dla każdego znaku alfabetu łacińskiego: (3.) jeśli nie chcemy dodać wykluczonego znaku to (4.) sprawdź pozycję znaku w kluczu. (5.) Jeśli znak nie występuje to (6.) dopisz go.

Szyfrowanie danych

Funkcja szyfrująca dane oczekuje podania trzech argumentów: tekst - tekst do zaszyfrowania, klucz - 24 znakowe słowo klucz użyte do szyfrowania oraz cyfry - 10 cyfrowy tekst.

C++
C#
  1. string szyfruj(string tekst, string klucz, string cyfry) {
  2.   string wynik = "";
  3.   for (int i = 0; i < tekst.length(); i++) {
  4.     size_t poz = klucz.find(tekst[i]);
  5.     if (poz != string::npos) {
  6.       int y = poz / 8, x = poz % 8;
  7.       if (y != 0)
  8.         wynik += cyfry[7 + y];
  9.       wynik += cyfry[x];
  10.     } else {
  11.       wynik += tekst[i];
  12.     }
  13.   }
  14.   return wynik;
  15. }

(2.) Przygotuj zmienną wynikową. Następnie (3.) dla każdego znaku tekstu jawnego: (4.) wyszukaj jego pozycję w kluczu. (5.) Jeśli znak występuje to: (6.) oblicz jego pozycję w tabelce, a następnie (7. - 9.) określ jak dany znak ma zostać zaszyfrowany. Jeśli szyfrowany znak jest nieznany to (11.) tylko przepisz znak. Na koniec (14.) zwróć zmienną wynik.

Rozszyfrowanie danych

Funkcja deszyfrująca przyjmuje te same argumenty co szyfrująca z tą różnicą, że w argumencie tekst znajduje sie szyfrogram, a nie tekst jawny.

C++
C#
  1. string rozszyfruj(string tekst, string klucz, string cyfry) {
  2.   string wynik = "";
  3.   for (int i = 0; i < tekst.length(); i++) {
  4.     size_t poz = cyfry.find(tekst[i]);
  5.     if (poz != string::npos) {
  6.       if (poz > 7) {
  7.         size_t pozx = cyfry.find(tekst[i + 1]);
  8.         wynik += klucz[(poz - 7) * 8 + pozx];
  9.         i++;
  10.       } else {
  11.         wynik += klucz[poz];
  12.       }
  13.     } else {
  14.       wynik += tekst[i];
  15.     }
  16.   }
  17.   return wynik;
  18. }

(2.) Przygotuj zmienną wynikową. Następnie (3.) dla każdego znaku szyfrogramu: (4.) wyszukaj jego pozycję w słowie kluczu cyfry. (5.) Jeśli cyfra występuje to: (6.) sprawdź numer pozycji. W ten sposób określamy czy dana cyfra jest nagłówkiem kolumn czy wierszy. Jeśli cyfra jest nagłówkiem wiersz to: (7.) pobierz kolejny znak i określ w ten sposób numer kolumny (numer wiersza mamy) i (8.) wybierz odpowiedni znak z klucza. Jednak jeśli pierwsza cyfra oznacza kolumnę to (11.) przyjmij, że znak znajduje się w pierszym wierszu. Jeśli podczas deszyfrowania natrafimy na nieznany znak to (14.) przypiszmy go. Na sam koniec działania funkcji zwracamy (17.) wartość w zmiennej wynik.

Testowanie funkcji

Napisane funkcje można przetestować przy pomocy poniższego fragmentu kodu. Program wczyta od użytkownika potrzebne dane, a następnie wypisze zaszyfrowany tekst, a potem go rozszyfruje.

C++
C#
  1. int main() {
  2.   string klucz, cyfry, tekst;
  3.   cout << "Podaj slowo klucz (bez liter J i X)\n";
  4.   cin >> klucz;
  5.   cout << "Podaj cyfry klucze\n";
  6.   cin >> cyfry;
  7.   klucz = uzupelnijKlucz(klucz);
  8.   cout << "Podaj tekst do zaszyfrowania\n";
  9.   cin.ignore();
  10.   getline(cin, tekst);
  11.   string szyfrogram = szyfruj(tekst, klucz, cyfry);
  12.   cout << "\nZaszyfrowany tekst:\n" << szyfrogram;
  13.   string tekstJawny = rozszyfruj(szyfrogram, klucz, cyfry);
  14.   cout << "\nRozszyfrowany tekst:\n" << tekstJawny;
  15.   system("pause");
  16.   return 0;
  17. }
Zadania
Zadanie 1
Kod źródłowy Zadanie 1Kod źródłowy Zadanie 1