Strona główna » Algorytmy » Szyfry » Quagmire IV
 

Quagmire IV

· Quagmire I · Quagmire II ·

Wstęp

Quagmire IV to ostatnia wariacja szyfru podstawieniowego o tej samej nazwie. Do szyfrowania alfabetu oraz do szyfrowania tabeli używa się różnych kluczy co czyni tą wersję najbezpieczniejszą.

Opis Szyfrowania

Część procesu jest podobno jak w Quagmire I. W celu zaszyfrowania informacji przy pomocy szyfru Quagmire IV należy wpierw określić dwa hasła oraz słowo klucz. Pierwsze hasło służy do utworzenia zaszyfrowanego alfabetu. W celu jego utworzenia należy ustalić hasło, a następnie zostawić tylko pierwsze wystąpienia każdej litery i uzupełnić nie wystepującymi znakami z alfabetu. Ostatecznie zaszyfrowany alfabet powinien mieć taką samą długość co przyjęty alfabet oraz powinien mieć wszystkie znaki różne. W tej wariacji tylko zaszyfrowany alfabet jest używany.

Następnie na podstawie słowa klucz tworzy się tabelką podstawień. W celu utworzenia takiej tabelki w pierwszym wierszu należy zapisać zaszyfrowany alfabet (po jednej literze w każdej kolumnie) utworzony na podstawie drugiego hasła. Pod literą 'A' w pierwszym wierszu należy zapisać pionowo słowo kluczowe. Każdy wiersz uzupełnia się literami (pierwszego) alfabetu zaszyfrowanego poprzez zapisanie po lewej i po prawej znanej litery w wierszu odpowiedniego poprzednie i kolejne znaki, które są wybierane cyklicznie z zaszyfrowanego alfabetu.

W celu zaszyfrowania danych należy pogrupować litery po tyle znaków jaką długość ma słowo kluczowe. Następnie każdy kolejny znak jest zamieniany na podstawie tabeli podstawień. Litera c jest szukana w pierwszym wierszu tabeli, a następnie pobierany jest znak w tej samej kolumnie co został znaleziony znak, ale k pozycji dalej, gdzie k to numer znaku w grupie (indeksujemy od 0). Po zamianie wszystkich znaków otrzymujemy szyfrogram.

Przykład

Poniżej zostanie przedstawiony proces szyfrowania tekstu "TAJNAINFORMACJA" przy pomoc haseł "TAJNEHASLO", "DRUGIETAJNEHASLO" i słowem kluczowym "KLUCZ". Pierwszy etap polega na utworzeniu zaszyfrowanego alfabetu. W tym celu wpierw usuwamy powtarzające się litery (prócz pierwszego ich wystąpienia) i otrzymujemy "TAJNEHSLO", a następnie uzupełniamy przy pomocy liter alfabetu jawnego: "TAJNEHSLOBCDFIKMNPQRUVWXYZ".

W podobny sposób należy postąpić z drugim hasłem "DRUGIETAJNEHASLO". Likwidowane są wszystkie duplikujące się litery: "DRUGIETAJNHSLOBCFKMPQVWXYZ"

Teraz można przejść do tworzenia tabeli. W pierwszy wiersz wpisany zostaje zaszyfrowany alfabet, utworzony na podstawie drugiego hasła, a klucz zostanie zapisany w kolumnie pod literą 'A'. Następnie każdy wiersz zostaje uzupełniony pierwszym zaszyfrowanym alfabetem tak, że na prawo są kolejne znaki, a na lewo poprzednie znaki, które są wybierane cyklicznie.

DRUGIETAJNHSLOBCFKMPQVWXYZ
LOBCDFIKMNPQRUVWXYZTAJNEHS
TAJNEHSLOBCDFIKMNPQRUVWXYZ
IKMNPQRUVWXYZTAJNEHSLOBCDF
NEHSLOBCDFIKMNPQRUVWXYZTAJ
QRUVWXYZTAJNEHSLOBCDFIKMNP

Tabela podstawień została utworzona. Przed rozpoczęciem szyfrowania warto pogrupować litery. W tym przypadku słowo klucz ma dokładnie 5 liter, więc po tyle samo znaków będzie mieć każda z grup.

TAJNAINFORMACJA

Pod literą 'T' w pierwszy wierszu znajduje się literka 'I'. Następna litera 'A' zostanie zastąpiona przez literę w tej samej kolumnie dwa wiersze niżej czyli 'L'. Poniżej została przedstawiona pełna lista zamian:

ZnakTAJNAINFORMACJA
W grupie123451234512345
SzyfrogramOAKSRWNZDDYAXHR

Otrzymany szyfrogram to "OAKSRWNZDDYAXHR".

Implementacja

Uzupełnianie alfabetu

Funkcja uzupelnijAlfabet() przyjmuje jeden argument a - hasło użyte do szyfrowania. Wynikiem działania funkcji jest zaszyfrowany alfabet.

Proces uzupełniania alfabet został podzielony na dwa etapy. (2. - 4.) W pierwszym przepisywane są kolejne znaki hasła pod warunkiem, że do tej pory taka litera nie została przepisana, a drugi etap polega na (5. - 7.) sprawdzeniu, których liter alfabetu brakuje.

C++
C#
  1. static string uzupelnijAlfabet(string a) {
  2.   string w = "";
  3.   for (int i = 0; i < a.Length; i++)
  4.     if (w.IndexOf(a[i]) == -1)
  5.       w += a[i];
  6.   for (char i = 'A'; i <= 'Z'; i++)
  7.     if (w.IndexOf(i) == -1)
  8.       w += i;
  9.   return w;
  10. }

Szyfrowanie danych

Tym razem nie będzie tworzona żadna tabela używana do szyfrowania. Zamiast tego w każdej iteracji na bieżąco będzie wyliczana odpowiednia litera. Ma to na celu zaoszczęzenie miejsca w pamięci. Do zaszyfrowania danych funkcja szyfruj() potrzebuje podania następujących argumentów: tekst - tekst jawny do zaszyfrowania, alfabet1 i alfabet2 - zaszyfrowane alfabety utworzone na podstawie haseł, klucz - klucz użyty do szyfrowania. Przyjmuje się, że wyróżnionym znakiem jest znak 'A'.

C++
C#
  1. static string szyfruj(string tekst, string alfabet1, string alfabet2, string klucz) {
  2.   string w = "";
  3.   int n = klucz.Length;
  4.   int wyroznione = alfabet2.IndexOf("A");
  5.   for (int i = 0; i < tekst.Length; i++) {
  6.     int pozycja = alfabet1.IndexOf(tekst[i]);
  7.     int numer = alfabet1.IndexOf(klucz[i % n]) - wyroznione;
  8.     w += alfabet1[(pozycja + numer) % 26];
  9.   }
  10.   return w;
  11. }

(2.) Przygotuj zmienną pod wynik, (3.) pobierz długość klucza i (4.) sprawdź gdzie znajduje się wyróżniony znak. (Znak ten można zmienić). (5.) W pętli: (6.) znajdź pozycję znaku w alfabecie głównym, a potem (7.) sprawdź gdzie znak występuje w kolejnym wierszu szyfrującym wybieranym cyklicznie. Linijka ta zastępuje tworzenie tabeli szyfrujące, a (8.) w następnej obie pozycje są składane tak, aby otrzymać wartość pobieraną z tablicy szyfrujące. Na koniec (10.) zwrócony jest znaleziony szyfrogram.

Rozszyfrowanie danych

Funkcja rozszyfruj() działa analogicznie do funkcji szyfruj(). W tym przypadku została zamieniona kolejność wybierania z tabeli.

C++
C#
  1. static string rozszyfruj(string tekst, string alfabet1, string alfabet2, string klucz) {
  2.   string w = "";
  3.   int n = klucz.Length;
  4.   int wyroznione = alfabet2.IndexOf("A");
  5.   for (int i = 0; i < tekst.Length; i++) {
  6.     int pozycja = alfabet1.IndexOf(tekst[i]);
  7.     int numer = alfabet1.IndexOf(klucz[i % n]) - wyroznione;
  8.     w += alfabet1[(pozycja - numer + 26) % 26];
  9.   }
  10.   return w;
  11. }

Testowanie funkcji

Poprawność działania napisanych funkcji można przetestować przy pomocy poniżeszego fragmentu kodu, który pozwala na wczytanie danych od użytkownika.

C++
C#
  1. static void Main(string[] args) {
  2.   string haslo1 = "", haslo2 = "", klucz = "", tekst = "";
  3.   Console.Write("Podaj pierwsze słowo szyfrujące: ");
  4.   haslo1 = Console.ReadLine();
  5.   string alfabet1 = uzupelnijAlfabet(haslo1);
  6.   Console.Write("Podaj drugie słowo szyfrujące: ");
  7.   haslo2 = Console.ReadLine();
  8.   string alfabet2 = uzupelnijAlfabet(haslo2);
  9.   Console.Write("Podaj słowo klucz: ");
  10.   klucz = Console.ReadLine();
  11.   Console.Write("Podaj tekst do zaszyfrowania: ");
  12.   tekst = Console.ReadLine();
  13.   string szyfrogram = szyfruj(tekst, alfabet1, alfabet2, klucz);
  14.   string tekstJawny = rozszyfruj(szyfrogram, alfabet1, alfabet2, klucz);
  15.   Console.Write("\nSzyfrogram to: {0}\n", szyfrogram);
  16.   Console.Write("\nPo rozszyfrowaniu: {0}\n", tekstJawny);
  17.   Console.ReadKey();
  18. }