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

Szyfr Mafeking

Opis szyfru

Szyfrowanie polega na zamianie każdej litera na parę znaków zgodnie z tabelką:

MAFEKING
1ABCDEFGH
2IJKLMNOP
3RSTUWXYZ

W celu zaszyfrowania pojedynczego znaku należy odczytać nagłówek kolumny i wiersza, a następnie w tej kolejności zapisać w wynikowym tekście. Przykładowo kiedy chcemy zaszyfrować literę A zamieniamy ją na M1. Z kolei literę Z zaszyfrujemy jako G3. Podczas deszyfrowania należy pamiętać, aby brać kolejne dwa znaki i odczytać literę z tabelki: cyfra oznacza numer wiersza, a litera to nagłówek kolumny. Przykładowo zaszyfrowany tekst F3K1A3F3 to TEST.

Warto zauważyć, że standardowy alfabet łaciński składa się z 26 znaków przez co 2 znaki znajdują się poza tabelką. W przypadku szyfru Mafeking zostały usunięte litery Q oraz V.

Szyfrowanie

Szyfrowanie polega na zamianie każdego znaku na dwa inne. Z tego powodu nie istnieje potrzeba pisania specjalnej części kodu do wyliczania tekstu wynikowgo. Należy jednak wziąć pod uwagę, aby prawidłowo usunąć litery Q i V z alfabetu.

  1. char* cipher(const char* txt){
  2.   char* code = "MAFEKING\0";
  3.   int dl = 2*strlen(txt);
  4.   char* wynik = new char[dl + 1];
  5.   for(int i = 0; txt[i]; i++){
  6.     char char_code = (txt[i] > 'Q' ? (txt[i] > 'V' ? txt[i] - 2 : txt[i] - 1) : txt[i]) - 'A';
  7.     wynik[2*i] = code[char_code % 8];
  8.     wynik[2*i + 1] = char_code / 8 + '1';
  9.   }
  10.   wynik [dl] = '\0';
  11.   return wynik;
  12. }

(2.) Deklarujemy pomocniczą zmienną code i zapisujemy w niej klucz. Użyjemy jej do odczytywania nagłówka kolumny dla rozpatrywanego znaku. (3.) Wyliczamy długość tekstu wynikowego. W tym przypadku każdy znak to dwa inne, więc wystarczy podwoić długość txt. (4.) Alokujemy pamięć pod tekst wynikowy. (5.) Dla każdego znaku w txt: (6.) wyliczamy jego pozycję w alfabecie. W obliczeniach uwzględniamy przesunięciu spowodowane usunięciem Q i V. (7.) Pobieramy nagłówek kolumny z code i (8.) obliczamy nagłówek wiersza. Po wykonaniu pętli (10.) dopisujemy na końcu znak końca danych, (11.) zwracamy wynik.

Deszyfrowanie

Podczas deszyfrowania będziemy potrzebowali wyszukać literę w zmiennej code. Dzięki temu będziemy wiedzieć w której kolumnie leży zaszyfrowany znak. To zadanie realizuje funkcja pomocnicza findCharInList():

  1. int findCharInList(const char* txt, const char c){
  2.   for (int i = 0; txt[i]; i++){
  3.     if(txt[i] == c){
  4.       return i;
  5.     }
  6.   }
  7.   return -1;
  8. }

Z kolei właściwa funkcją deszyfrująca wygląda tak:

  1. char* decipher(const char* txt){
  2.   char* code = "MAFEKING\0";
  3.   int dl = strlen(txt)/2;
  4.   char* wynik = new char[dl];
  5.   for(int i = 0; txt[i];i+=2){
  6.     char char_code = 'A' + 8 * (txt[i + 1] - '1') + findCharInList(code, txt[i]);
  7.     if(char_code >= 'Q') char_code++;
  8.     if(char_code >= 'U') char_code++;
  9.     wynik[i/2] = char_code;
  10.   }
  11.   wynik[dl] = '\0';
  12.   return wynik;
  13. }

(2.) Przy deszyfrowaniu również użyjemy zmiennej pomocniczej code w której przechowamy nagłówki kolumn tabeli. (3.) Długość tekstu wynikowego będzie dwa razy mniejsza od wejściowego. (4.) Alokujemy pamięć pod tekst wynikowy. (5.) Dopóki nie przejrzymy wszystkich znaków txt: (6.) Wyliczamy zaszyfrowany znak. Nie uwzględniamy tu przesunięcia spowodowanego wycięciem dwóch liter. Robimy to w linijkach (7., 8.), gdzie zwiększamy odpowiedni znaki. (9.) Dopisujemy wyliczony znak na koniec wyniku. (11.) Dopisujemy na koniec \0, (12.) zwracamy wynik.

Testowanie kodu

Funkcja main(), która przetestuje działanie programu wygląda następująco:

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

Zadania

Zadanie 1

Napisz funkcję szyfrującą i deszyfrująca metodą Mafekinga, której działanie nie będzie polegało na deklarowaniu pomocniczej zmiennej code w której będzie przechowywany klucz MAFEKING. Wskazówka: użyj w tym celu np. instrukcji switch.