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

Szyfr Morbid

Wstęp

Szyfr Morbid to szyfr podstawieniowy, który szyfruje przy pomocy klucza złożonego z cyfr tekst zapisany alfabetem Morse'a. W teorii przejście z liter na alfabet Morse'a i potem na cyfry zwiększa bezpieczeństwo danych, ale jest możliwe jego złamanie.

Definicja

Przed szyfrowaniem należy ustalić słowo klucz złożone z 9 cyfr (albo innych różnych 9 znaków). Oznaczmy i-tą literę słowa przez si. Na podstawie podanego klucza tworzy się tabelkę szyfrujacą:

Kluczs1s2s3s4s5s6s7s8s9
Znak 1...---xxx
Znak 2.-x.-x.-x

Szyfrowanie polega najpierw na zakodowaniu wiadomości alfabetem Morse'a, a następnie wybieraniu kolejnych par znaków i dopasowania ich do tabeli. W celu dopasowanie pierwszy znak pary należy znaleźć w wierszu Znak 1, a drugi w wierszu Znak 2. Daną parę będzie szyfrować znak w wierszu Klucz w kolumnie w której znajduje się para. Pomiędzy każdym znakiem musi znaleźć się znak 'x', a pomiędzy każdym wyrazem wyrażenie 'xx'. Proces ten jest powtarzany dla każdej pary znaków.

W celu rozszyfrowania zaszyfrowanej wiadomości należy najpierw znaki zamienić zgodnie z tabelką na pary znaków, a dopiero później rozkodować alfabet Morse'a jeśli istnieje takowa potrzeba. Należy pamiętać, że pomiędzy znakami występuje dodatkowy znak 'x', a pomiędzy wyrazami 'xx'.

Przykład

Niech szyfrowanym tekstem jawnym będzie wyrażenie "TAJNE DANE" przy pomocy klucza "928371456". Pierwszy krok polega na utworzeniu tabelki:

Klucz928371456
Znak 1...---xxx
Znak 2.-x.-x.-x

Następnie należy zakodować tekst przy pomocy alfabetu Morse'a:

KluczTAJNE DANE
Morse-.-.----.. -...--..

Następnie pomiędzy każdą zamianę znaku na kod Morse'a należy wpisać 'x' i pogrupować dane w pary. Znak przerwy jest zamieniany na 'xx'. Każda para jest zamieniana na odpowiednią cyfrę zgodnie z tabelką utworzoną w pierszym kroku:

Morse-x.-x.---x-.x.xx-..x.-x-.x.x
Szyfrogram12471346382588

Ostateczny szyfrogram to "12471346382588". Można go roszyfrować wykonując opisane polecenia od końca.

Implementacja

Strategia

Kodowanie Morse'a

Do projektu została dołączona biblioteka 'morse' oraz plik z alfabetem Morse'a z funkcjami, które zostały opisane w alfabecie na temat alfabetu Morse'a. Należą do nich:

Zamiana pary

W celu rozwiązania problemu z parami zobaczmy tworzoną tabelkę jeszcze raz, ale zamieńmy znak '.' na 0, znak '-' na 1, a znak 'x' na 2. Wtedy otrzymamy:

Kluczs1s2s3s4s5s6s7s8s9
Znak 1000111222
Znak 2012012012

Jeśli byśmy uznali, że pierwszy znak, a po nim drugi tworzą liczbę to byłyby to kolejne liczby z systemu trójkowego - i-ta kolumna miałaby wartość: wartość Znak 1 razy trzy plus wartość Znak 2. Wtedy:

Znak 1000111222
Znak 2012012012
Wartość012345678

Wyliczoną wartość można wykorzystać do wybierania i-tego znaku z klucza (przyjmując indeksowanie od 0).

Szyfrowanie

Funkcja szyfruj() przyjmuje dwa argumenty: data - oryginalny tekst do zaszyfrowania oraz code - kod szyfrujący dane. Wynikiem działania funkcji jest szyfrogram.

C++
C#
  1. string szyfruj(string data, string code) {
  2.   string temp = "";
  3.   for (int i = 0; data[i]; i++) {
  4.     if (data[i] == ' ') {
  5.       temp += "x";
  6.     } else {
  7.       temp += morse::znajdzOdpowiednikZnaku(string(1, data[i])) + "x";
  8.     }
  9.   }
  10.   if (temp.length() % 2 == 1)
  11.     temp += 'x';
  12.   string w = "";
  13.   for (int i = 0; i < temp.length(); i += 2) {
  14.     int w1 = naCyfry(temp[i]);
  15.     int w2 = naCyfry(temp[i + 1]);
  16.     int poz = w1 * 3 + w2;
  17.     w += code[poz];
  18.   }
  19.   return w;
  20. }

Najpierw (2. - 10.) tekst jest zamieniany na kod Morse'a i (11. - 12.) dopisywany jest znak 'x' jeśli długość danych do zaszyfrowania jest niaprzysta(inaczej możliwa jest utrata jednego znaczka i w konsekwencji zmiana tekstu). Dalsza część polega na (13. - 21.) utworzeniu szyfrogramu poprzez (16.) wyliczenie, który znak z klucza pobrać.

Do szyfrowania danych program korzysta dodatkowo z funkcji naCyfry(), która dla podanego znaku c zwraca jego wartość od 0 do 2 zgodnie ze strategią podaną wcześniej.

C++
C#
  1. int naCyfry(char c) {
  2.   switch (c) {
  3.     case '.': return 0;
  4.     case '-': return 1;
  5.     default: return 2;
  6.   }
  7. }

Rozszyfrowanie

Funkcja rozszyfruj() przyjmuje dwa argumenty: data - tekst do rozszyfrowania oraz code - kod szyfrujący dane. Wynikiem działania funkcji jest szyfrogram.

C++
C#
  1. string rozszyfruj(string data, string code) {
  2.   string temp = "";
  3.   for (int i = 0; data[i]; i++) {
  4.     int pos = code.find(data[i]);
  5.     temp += naZnaki(pos / 3);
  6.     temp += naZnaki(pos % 3);
  7.   }
  8.   string w = "", kod = "";
  9.   for (int i = 0; temp[i]; i++) {
  10.     kod = "";
  11.     while (temp[i] != 'x') {
  12.       kod += temp[i];
  13.       i++;
  14.     }
  15.     if (kod != "")
  16.       w += morse::znajdzOdpowiednikKodu(kod);
  17.     else if (temp[i] == temp[i - 1] && temp[i] == 'x')
  18.       w += " ";
  19.   }
  20.   return w;
  21. }

(2. - 7.) Najpierw przekazany szyfrogram należy rozszyfrować zamieniając znaki na pary znaków czyli do postaci kodu Morse'a. Następnie odszyfrowany tekst Morse'a (8. - 20.) należy rozkodować i (21.) zwróć wynik.

Do szyfrowania danych program korzysta dodatkowo z funkcji naZnaki(), która dla podanej wartości c zwraca znak jej odpowiadający.

C++
C#
  1. char naZnaki(int c) {
  2.   switch (c) {
  3.     case 0: return '.';
  4.     case 1: return '-';
  5.     default: return 'x';
  6.   }
  7. }

Testowanie funkcji

W celu przetestowania kodu można skorzystać z poniższego fragmentu, który wczyta od użytkownika tekst do zaszyfrowania oraz klucz szyfrujący:

C++
C#
  1. int main() {
  2.   morse::wczytajAlfabet();
  3.   string txt, code;
  4.   cout << "Podaj tekst do zaszyfrowania:" << endl;
  5.   getline(cin, txt);
  6.   cout << "Podaj kod szyfrowania:" << endl;
  7.   getline(cin, code);
  8.   cout << "\nSzyfrogram:" << endl;
  9.   string txtk = szyfruj(txt, code);
  10.   cout << txtk << endl;
  11.   cout << "\nTekst jawny:" << endl;
  12.   string txtr = rozszyfruj(txtk, code);
  13.   cout << txtr << endl;
  14.   system("pause");
  15.   return 0;
  16. }
Zadania
Zadanie 1
Kod źródłowy Zadanie 1Kod źródłowy Zadanie 1