C++

Szyfr Playfair – objaśnienie i implementacja

playfair_miniatura

Kryptologia to dziedzina, która jest nierozłącznie kojarzona z informatyką. Jest tak nie bez powodu - m.in. to właśnie dzięki wszelakiej maści szyfrom, dbamy o bezpieczeństwo naszych danych. Zagłębianie się w tematykę kryptologii warto rozpocząć od zapoznania się z jednym z wielu szyfrów, którym może być chociażby szyfr Playfair.

Trochę historii

Szyfr Playfair został opracowany przez Charlesa Wheatstone – angielskiego wynalazcę. Szyfr ten zawdzięcza swoją nazwę baronowi Lyonowi Playfair, który stał za jego popularyzacją. Korzysta on z jednego klucza do szyfrowania i deszyfrowania wiadomości, należy więc do grupy szyfrów symetrycznych. Jest to także pierwszy z szyfrów, w którym tekst szyfrowany dzielony jest nie na pojedyncze litery (jak chociażby w szyfrze cezara), a na pary liter, zwane digrafami.

Szyfr Playfair był wykorzystywany przez brytyjską armię podczas wojny burskiej. Jest on stosunkowo prosty w użyciu, dzięki czemu nadawał się idealnie do zastosowań polowych.

Szyfr Playfair - zasada działania

Przejdźmy jednak do meritum, jakim jest zasada działania szyfru. Do rozpoczęcia działania potrzebujemy klucza oraz tekstu do szyfrowania. Za klucz przyjmijmy słowo „binary”, a naszym tekstem jawnym będzie słowo „programowanie”.

W pierwszej kolejności potrzebujemy stworzyć kwadrat szyfrowania, który jest niczym innym jak tablicą o wymiarach 5x5. W kolejnym kroku wpisujemy litery klucza w kolejne komórki tablicy, pomijając wpisane już znaki (przykładowo klucz „binarnie” zostałby zapisany jako „binare”).

szyfr Playfair - tablica szyfrowania

Następnie wpisujemy do tablicy pozostałe, nie wpisane jeszcze litery alfabetu (pomijając literę „j”, która zmieniana jest na literę „i”, ze względu na ograniczony rozmiar tablicy).2

szyfr Playfair - wypełniona tablica szyfrowania

Mając już gotową tablicę, możemy przystąpić do szyfrowania. Pierwszy krok, który musimy wykonać, to podzielenie szyfrowanego tekstu na pary liter. W naszym przypadku, otrzymamy: pr-og-ra-mo-wa-ni-e. Ze względu na nieparzystą liczbę liter w naszym tekście, dodajemy na koniec tekstu literę „z”, otrzymując: pr-og-ra-mo-wa-ni-ez. Szyfrowanie digrafów podzielone jest na kilka przypadków:

1)Obie litery są w tej samej kolumnie – W tym przypadku, zamieniamy litery, na te znajdujące się pod nimi. Przykładowo OG, zamienia się UO. W przypadku gdy którakolwiek z liter którą mamy zamienić, znajduje się na końcu kolumny, podczas zamiany bierzemy literę znajdującą się na początku tej samej kolumny

szyfr Playfair - tablica szyfrowania

2)Obie litery są w tym samym wierszu – Analogicznie do przypadku pierwszego, zamieniamy litery na te sąsiadujące z nimi po prawej stronie. Jeśli któraś z liter znajduje się na końcu wiersza, bierzemy pierwszą literę znajdującą się na początku wiersza. Przykładowo dwuznak RA, zostanie zamieniony na BR.

szyfr Playfair - tablica szyfrowania

3)Pozostałe przypadki – Gdy litery nie znajdują się w tej samej kolumnie ani wierszu, należy zlokalizować obie litery w tablicy. Następnie pierwszą literę zamieniamy ze znakiem znajdującym się na przecięciu wiersza litery pierwszej z kolumną litery drugiej. Przykładowo w digrafie PR, litera „p” zostanie zamieniona na literę „t”.

Druga z liter, zostaje natomiast zastąpiona znakiem znajdującym się na przecięciu kolumny litery pierwszej, z wierszem litery drugiej. Litera „r”, z tego samego dwuznaku zostanie więc zastąpiona literą „i”. Digraf PR zostanie więc przekształcony w TI.

Przechodząc przez cały proces, słowo „programowanie” zaszyfrowane przy użyciu klucza „binary”, będzie miało postać „tiuobrgtxnanfx”.

Odszyfrowywanie wiadomości znając procedurę szyfrowania nie należy do najtrudniejszych zadań – procedura jest zwyczajnie odwracana. Jeśli obie litery są w tej samej kolumnie, zamieniamy je na litery znajdujące się nad nimi. W przypadku gdy są w tym samym wierszu czytamy litery sąsiadujące z nimi po lewej stronie. W przypadku gdy litery znajdują się w innych kolumnach i wierszach, tak jak w przypadku szyfrowania szukamy przecięć, w kolejności wiersza litery pierwszej z kolumną litery drugiej, a następnie kolumny litery pierwszej, z wierszem litery drugiej.



O podstawach kryptolografii i innych metodach szyfrowania przeczytasz w tej książce

Szyfr Playfair – implementacje

Implementacja szyfru Playfair podzielona jest na kilka funkcji. W pierwszej kolejności należy przygotować odpowiednio klucz oraz tekst jawny. Z obu należy usunąć znaki białe i zamienić je na małe, bądź wielkie litery.

C++

void przygotowanie(string &klucz, string &tekstJawny) {
	if (klucz.length() == 0) {
		klucz = "binary";
	}
	if (tekstJawny.length() == 0) {
		tekstJawny = "programowanie";
	}

	//Usuniecie spacji
	klucz.erase(std::remove(klucz.begin(), klucz.end(), ' '), klucz.end());
	tekstJawny.erase(std::remove(tekstJawny.begin(), tekstJawny.end(), ' '), tekstJawny.end());

	//Zmiana wszystkich liter na male
	transform(klucz.begin(), klucz.end(), klucz.begin(), ::tolower);
	transform(tekstJawny.begin(), tekstJawny.end(), tekstJawny.begin(), ::tolower);

	//zamiana liter j na i
	replace(klucz.begin(), klucz.end(), 'j', 'i');
	replace(tekstJawny.begin(), tekstJawny.end(), 'j', 'i');

	//Jesli liczba liter jest nieparzysta dodajemy 'z' do tekstu jawnego
	if (tekstJawny.length() % 2 != 0) {
		tekstJawny += 'z';
	}
}

Java

private static String prepare(String wyraz) {
		//Usuniecie spacji
		wyraz = wyraz.replaceAll(" ", "");
				
			 
		//Zmiana wszystkich liter na male
		wyraz = wyraz.toLowerCase();
				
			 
		//zamiana liter j na i
		wyraz = wyraz.replaceAll("j", "i");
		
		return wyraz;
	}
	private static String przygotowanieKlucza(String wyraz) {
		if (wyraz.length() == 0) {
			wyraz = "binary";
		}
		return prepare(wyraz);
	}
	
	private static String przygotowanieTekstuJawnego(String wyraz) {
		if (wyraz.length() == 0) {
			wyraz = "programowanie";
		}
		wyraz = prepare(wyraz);
		if(wyraz.length() % 2 != 0) {
			wyraz = wyraz + "z";
		}
		return wyraz;
	}

Python

def prepareWord(word):
    word = str(word)
    word = word.replace(" ", "")
    word = word.lower()
    word.replace("j", "i")
    return word

def prepareKey(key):
    if len(key) == 0:
        key = "binary"
    return prepareWord(key)

def prepareText(text):
    if len(text) == 0:
        key = "programowanie"
    text = prepareWord(text)
    if len(text) % 2 != 0:
        text = text + "z"
    return text

Następnie generować będziemy tablicę szyfrowania o wymiarach 5x5. Następnie wykonujemy wszystkie kroki generowania tablicy. W poniższej implementacji korzystamy z pomocniczego stringa w celu sprawdzania, czy dane litery znajdują się już w tablicy. Wykonywane jest to przy pomocy metody find().

C++

void generowanieTablicy(string klucz, char tablicaSzyfru[5][5]) {
	
	string kontrolny = "";
	string alfabet = "abcdefghiklmnopqrstuvwxyz";

	int x = 0, y = 0;
	size_t pozycja;

	//Korzystajac z zaawansowanej petli przechodzimy przez kolejne znaki w kluczu
	for (char znak : klucz) {
		//Sprawdzamy czy dodany znak  znajduje się już w tablicy
		pozycja = kontrolny.find(znak);

		//Jesli nie dodajemy do tablicy i stringa kontrolnego
		if (pozycja == string::npos) {
			if (y == 5) {
				//Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
				//wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
				cout << "BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy" << endl;
				return;
			}

			//Dodajemy znak do kontrolnego stringa i tablicy
			kontrolny += znak;
			tablicaSzyfru[x][y] = znak;
			x++;

			//Jesli doszlismy do konca wiersza przechodzimy do kolejnego
			if (x == 5) {
				x = 0;
				y++;
			}

		}
	}

	for (char znak : alfabet) {
		pozycja = kontrolny.find(znak);

		if (pozycja == string::npos) {
			if (y == 5) {
				cout << "BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy" << endl;
				return;
			}

			kontrolny += znak;
			tablicaSzyfru[x][y] = znak;
			x++;

			if (x == 5) {
				x = 0;
				y++;
			}
		}
	}

	cout << "Tablica szyfrowania:" << endl;
	printTab(tablicaSzyfru);

}

Java

private static void generowanieTablicy(String klucz, char[][] tablicaSzyfru) {
		
		String kontrolny = "";
		String alfabet = "abcdefghiklmnopqrstuvwxyz";

		int x = 0, y = 0;
		int pozycja;

		//Korzystajac z zaawansowanej petli przechodzimy przez kolejne znaki w kluczu
		for (char znak : klucz.toCharArray()) {
			//Sprawdzamy czy dodany znak  znajduje się już w tablicy
			pozycja = kontrolny.indexOf(znak);

			//Jesli nie dodajemy do tablicy i stringa kontrolnego
			if (pozycja == -1) {
				if (y == 5) {
					//Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
					//wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
					System.out.println("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy");
					return;
				}

				//Dodajemy znak do kontrolnego stringa i tablicy
				kontrolny += znak;
				tablicaSzyfru[x][y] = znak;
				x++;

				//Jesli doszlismy do konca wiersza przechodzimy do kolejnego
				if (x == 5) {
					x = 0;
					y++;
				}

			}
		}

		for (char znak : alfabet.toCharArray()) {
			pozycja = kontrolny.indexOf(znak);

			if (pozycja == -1) {
				if (y == 5) {
					System.out.println("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy");
					return;
				}

				kontrolny += znak;
				tablicaSzyfru[x][y] = znak;
				x++;

				if (x == 5) {
					x = 0;
					y++;
				}
			}
		}

		System.out.println("Tablica szyfrowania:");
		printTab(tablicaSzyfru);

	}

Python

def generate(key, tab):
    kontrolny = ""
    alfabet = "abcdefghiklmnopqrstuvwxyz"

    x = 0
    y = 0
    pozycja = 0

    for znak in key:  # Korzystajac z petli przechodzimy przez kolejne znaki w kluczu
        pozycja = kontrolny.find(znak)  # Sprawdzamy czy dodany znak  znajduje się już w tablicy
        if pozycja == -1:  # Jesli nie dodajemy do tablicy i stringa kontrolnego
            if y == 5:  # Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
                print("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy")
                return  # wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
            kontrolny += znak
            tab[x][y] = znak
            x += 1
            if x == 5:
                x = 0
                y += 1
    for znak in alfabet:
        pozycja = kontrolny.find(znak)
        if pozycja == -1:
            if y == 5:
                print("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy")
                return
            kontrolny += znak
            tab[x][y] = znak
            x += 1
            if x == 5:
                x = 0
                y += 1
    print("Tablica szyfrowania:")
    printTab(tab)

Po wygenerowaniu tablicy korzystamy z funkcji pomocniczej do jej wyświetlenia.

C++

void printTab(char tab[5][5]) {
	cout << endl;
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			cout << tab[j][i] << " | ";
		}
		cout << endl;
	}
	cout << endl;
}

Java

private static void printTab(char[][] tablicaSzyfru) {
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				System.out.print(tablicaSzyfru[j][i] + " | ");
			}
			System.out.println();
		}
	}

Python

def printTab(tab):
    print()
    for x in range(5):
        for y in range(5):
            print(tab[x][y], end=" | ")
        print()
    print()

Oprócz funkcji wyświetlającej zawartość tablicy stworzona została struktura point przechowująca współrzędne punktu, która to wykorzystana zostaje w funkcji wyszukującej koordynaty danego znaku.

C++

//Struktura przechowująca pozycje znaku
struct point {
	int x;
	int y;
};

point* znajdzKoordynatyZnaku(char znak, char tablica[5][5]) {

	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			if (tablica[j][i] == znak) {
				point* koordynaty = new point;
				koordynaty->x = j;
				koordynaty->y = i;
				return koordynaty;
			}
		}
	}

	return nullptr;
}

Java

private static SimpleEntry<Integer, Integer> znajdzKoordynatyZnaku(char znak, char[][] tablica) { //wykorzystujemy istniejaca juz klase SimpleEntry z biblioteki java.util.AbstractMap
		 
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if (tablica[j][i] == znak) {
					SimpleEntry<Integer, Integer> koordynaty = new SimpleEntry<Integer, Integer>(j, i);
					return koordynaty;
				}
			}
		}
		return null;
	}

Python

class Point():
    x = 0
    y = 0

    def __init__(self, a, b):
        self.x = a
        self.y = b

def findCoords(znak, tab):
    for i in range(5):
        for j in range(5):
            if tab[j][i] == znak:
                p = Point(j, i)
                return p
    return None

Po przygotowaniu tablicy szyfrowania, przystępujemy do właściwego szyfrowania. Każdy krok szyfrowania rozpoczynamy od znalezienia współrzędnych obu rozpatrywanych znaków. Następnie przyrównując do siebie koordynaty x i y, odpowiadające za pozycję w wierszu i kolumnie, określamy przypadek. Nowe znaki z tablicy, zostają dodane do zaszyfrowanego ciągu znaków, według standardowych zasad.

C++

string szyfrowanie(string tekstJawny, char tablicaSzyfru[5][5]) {
	char pierwszyZnak, drugiZnak;
	point* koordynatyPierwszego;
	point* koordynatyDrugiego;
	string tekstZaszyfrowany = "";

	//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
	for (int x = 0; x < tekstJawny.length(); x += 2) {
		//Wyszukiwanie koordynatow obu znakow digrafu
		koordynatyPierwszego = znajdzKoordynatyZnaku(tekstJawny.at(x), tablicaSzyfru);
		koordynatyDrugiego = znajdzKoordynatyZnaku(tekstJawny.at(x + 1), tablicaSzyfru);

		if (koordynatyPierwszego == nullptr || koordynatyDrugiego == nullptr) {
			cout << "NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy" << endl;
			return "";
		}

		//Pierwszy przypadek
		if (koordynatyPierwszego->x == koordynatyDrugiego->x) {
			//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
			//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
			//w przypadku znaku bedacego ostatnim znakiem w kolumnie
			tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego->x][(koordynatyPierwszego->y + 1) % 5];
			tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego->x][(koordynatyDrugiego->y + 1) % 5];
		}
		//Drugi przypadek
		else if (koordynatyPierwszego->y == koordynatyDrugiego->y) {
			//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
			//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
			//w przypadku znaku bedacym ostatnim znakiem w wierszu
			tekstZaszyfrowany += tablicaSzyfru[(koordynatyPierwszego->x + 1) % 5][koordynatyPierwszego->y];
			tekstZaszyfrowany += tablicaSzyfru[(koordynatyDrugiego->x + 1) % 5][koordynatyDrugiego->y];
		}
		//Pozostale przypadki
		else {
			//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
			//przeciecia wiersza drugiego z kolumna pierwszego
			tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego->x][koordynatyPierwszego->y];
			tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego->x][koordynatyDrugiego->y];
		}
	}

	return tekstZaszyfrowany;
}

Java

private static String szyfrowanie(String tekstJawny, char[][] tablicaSzyfru) {
		SimpleEntry<Integer, Integer> koordynatyPierwszego;
		SimpleEntry<Integer, Integer> koordynatyDrugiego;
		String tekstZaszyfrowany = "";

		//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
		for (int x = 0; x < tekstJawny.length(); x += 2) {
			//Wyszukiwanie koordynatow obu znakow digrafu
			koordynatyPierwszego = znajdzKoordynatyZnaku(tekstJawny.charAt(x), tablicaSzyfru);
			koordynatyDrugiego = znajdzKoordynatyZnaku(tekstJawny.charAt(x + 1), tablicaSzyfru);

			if (koordynatyPierwszego == null || koordynatyDrugiego == null) {
				System.out.println("NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy");
				return "";
			}

			//Pierwszy przypadek
			if (koordynatyPierwszego.getKey() == koordynatyDrugiego.getKey()) {
				//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
				//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
				//w przypadku znaku bedacego ostatnim znakiem w kolumnie
				tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego.getKey()][(koordynatyPierwszego.getValue() + 1) % 5];
				tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego.getKey()][(koordynatyDrugiego.getValue() + 1) % 5];
			}
			//Drugi przypadek
			else if (koordynatyPierwszego.getValue() == koordynatyDrugiego.getValue() ) {
				//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
				//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
				//w przypadku znaku bedacym ostatnim znakiem w wierszu
				tekstZaszyfrowany += tablicaSzyfru[(koordynatyPierwszego.getKey() + 1) % 5][koordynatyPierwszego.getValue()];
				tekstZaszyfrowany += tablicaSzyfru[(koordynatyDrugiego.getKey() + 1) % 5][koordynatyDrugiego.getValue()];
			}
			//Pozostale przypadki
			else {
				//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
				//przeciecia wiersza drugiego z kolumna pierwszego
				tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego.getKey()][koordynatyPierwszego.getValue()];
				tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego.getKey()][koordynatyDrugiego.getValue()];
			}
		}

		return tekstZaszyfrowany;
	}

Python

def szyfrowanie(text, tab):
    coordsFirst = Point(0, 0)
    coordsSecond = Point(0, 0)
    encryptedText = ""

    for x in range(0, len(text), 2): #Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
        coordsFirst = findCoords(text[x], tab) #Wyszukiwanie koordynatow obu znakow digrafu
        coordsSecond = findCoords(text[x + 1], tab)

        if coordsFirst == None or coordsSecond == None:
            print("NIE ZNALEZIONO ZNAKU ", text[x],  " W TABLICY! - Zakonczenie pracy")
            return ""

        if coordsFirst.x == coordsSecond.x: #Pierwszy przypadek
            encryptedText += tab[coordsFirst.x][coordsFirst.y + 1] #Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
            encryptedText += tab[coordsSecond.x][(coordsSecond.y + 1) % 5] #Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
        else: #Drugi przypadek; Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
            if coordsFirst.y == coordsSecond.y: #Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
                encryptedText += tab[(coordsFirst.x + 1) % 5][coordsFirst.y]
                encryptedText += tab[(coordsSecond.x + 1) % 5][coordsSecond.y]
            else: #Pozostale przypadki
                encryptedText += tab[coordsSecond.x][coordsFirst.y] #Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
                encryptedText += tab[coordsFirst.x][coordsSecond.y] #przeciecia wiersza drugiego z kolumna pierwszego
    return encryptedText

Funkcja odszyfrowywania odwraca kolejność działań. Całość programu ma więc postać:

C++

//program wykonujacy
//szyfrowanie i deszyfrowanie Playfair
//Jan Żwirek

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

//Struktura przechowująca pozycje znaku
struct point {
	int x;
	int y;
};

void przygotowanie(string &klucz, string &tekstJawny);
void generowanieTablicy(string klucz, char tablicaSzyfru[5][5]);
string szyfrowanie(string tekstJawnym, char tablicaSzyfru[5][5]);
string odszyfrowywanie(string tekstZaszyfrowany, char tablicaSzyfru[5][5]);
void printTab(char tab[5][5]);
point* znajdzKoordynatyZnaku(char znak, char tablica[5][5]);

int main() {
	string klucz, tekst, tekstZaszyfrowany;
	char tablicaSzyfru[5][5];

	cout << "Podwaj klucz i tekst jawny bez liczb oraz znakow specjalych!" << endl;
	cout << "Wprowadz klucz: ";
	std::getline(std::cin, klucz);

	cout <<  "Wprowadz tekst do zaszyfrowania: ";
	std::getline(std::cin, tekst);

	cout << "\nTekst jawny: " << tekst << endl;
	cout << "Klucz: " << klucz << endl;
	przygotowanie(klucz, tekst);
	generowanieTablicy(klucz, tablicaSzyfru);

	tekstZaszyfrowany = szyfrowanie(tekst, tablicaSzyfru);
	cout << "Tekst zaszyfrowany: " << tekstZaszyfrowany << endl;
	cout << "Tekst odszyfrowany: " << odszyfrowywanie(tekstZaszyfrowany, tablicaSzyfru) << endl;
}

void przygotowanie(string &klucz, string &tekstJawny) {
	if (klucz.length() == 0) {
		klucz = "binary";
	}
	if (tekstJawny.length() == 0) {
		tekstJawny = "programowanie";
	}

	//Usuniecie spacji
	klucz.erase(std::remove(klucz.begin(), klucz.end(), ' '), klucz.end());
	tekstJawny.erase(std::remove(tekstJawny.begin(), tekstJawny.end(), ' '), tekstJawny.end());

	//Zmiana wszystkich liter na male
	transform(klucz.begin(), klucz.end(), klucz.begin(), ::tolower);
	transform(tekstJawny.begin(), tekstJawny.end(), tekstJawny.begin(), ::tolower);

	//zamiana liter j na i
	replace(klucz.begin(), klucz.end(), 'j', 'i');
	replace(tekstJawny.begin(), tekstJawny.end(), 'j', 'i');

	//Jesli liczba liter jest nieparzysta dodajemy 'z' do tekstu jawnego
	if (tekstJawny.length() % 2 != 0) {
		tekstJawny += 'z';
	}
}

void generowanieTablicy(string klucz, char tablicaSzyfru[5][5]) {
	
	string kontrolny = "";
	string alfabet = "abcdefghiklmnopqrstuvwxyz";

	int x = 0, y = 0;
	size_t pozycja;

	//Korzystajac z zaawansowanej petli przechodzimy przez kolejne znaki w kluczu
	for (char znak : klucz) {
		//Sprawdzamy czy dodany znak  znajduje się już w tablicy
		pozycja = kontrolny.find(znak);

		//Jesli nie dodajemy do tablicy i stringa kontrolnego
		if (pozycja == string::npos) {
			if (y == 5) {
				//Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
				//wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
				cout << "BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy" << endl;
				return;
			}

			//Dodajemy znak do kontrolnego stringa i tablicy
			kontrolny += znak;
			tablicaSzyfru[x][y] = znak;
			x++;

			//Jesli doszlismy do konca wiersza przechodzimy do kolejnego
			if (x == 5) {
				x = 0;
				y++;
			}

		}
	}

	for (char znak : alfabet) {
		pozycja = kontrolny.find(znak);

		if (pozycja == string::npos) {
			if (y == 5) {
				cout << "BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy" << endl;
				return;
			}

			kontrolny += znak;
			tablicaSzyfru[x][y] = znak;
			x++;

			if (x == 5) {
				x = 0;
				y++;
			}
		}
	}

	cout << "Tablica szyfrowania:" << endl;
	printTab(tablicaSzyfru);

}

string szyfrowanie(string tekstJawny, char tablicaSzyfru[5][5]) {
	char pierwszyZnak, drugiZnak;
	point* koordynatyPierwszego;
	point* koordynatyDrugiego;
	string tekstZaszyfrowany = "";

	//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
	for (int x = 0; x < tekstJawny.length(); x += 2) {
		//Wyszukiwanie koordynatow obu znakow digrafu
		koordynatyPierwszego = znajdzKoordynatyZnaku(tekstJawny.at(x), tablicaSzyfru);
		koordynatyDrugiego = znajdzKoordynatyZnaku(tekstJawny.at(x + 1), tablicaSzyfru);

		if (koordynatyPierwszego == nullptr || koordynatyDrugiego == nullptr) {
			cout << "NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy" << endl;
			return "";
		}

		//Pierwszy przypadek
		if (koordynatyPierwszego->x == koordynatyDrugiego->x) {
			//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
			//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
			//w przypadku znaku bedacego ostatnim znakiem w kolumnie
			tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego->x][(koordynatyPierwszego->y + 1) % 5];
			tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego->x][(koordynatyDrugiego->y + 1) % 5];
		}
		//Drugi przypadek
		else if (koordynatyPierwszego->y == koordynatyDrugiego->y) {
			//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
			//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
			//w przypadku znaku bedacym ostatnim znakiem w wierszu
			tekstZaszyfrowany += tablicaSzyfru[(koordynatyPierwszego->x + 1) % 5][koordynatyPierwszego->y];
			tekstZaszyfrowany += tablicaSzyfru[(koordynatyDrugiego->x + 1) % 5][koordynatyDrugiego->y];
		}
		//Pozostale przypadki
		else {
			//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
			//przeciecia wiersza drugiego z kolumna pierwszego
			tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego->x][koordynatyPierwszego->y];
			tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego->x][koordynatyDrugiego->y];
		}
	}

	return tekstZaszyfrowany;
}

string odszyfrowywanie(string tekstZaszyfrowany, char tablicaSzyfru[5][5])
{

	char pierwszyZnak, drugiZnak;
	point* koordynatyPierwszego;
	point* koordynatyDrugiego;
	string tekstJawny = "";

	//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
	for (int x = 0; x < tekstZaszyfrowany.length(); x += 2) {
		//Wyszukiwanie koordynatow obu znakow digrafu
		koordynatyPierwszego = znajdzKoordynatyZnaku(tekstZaszyfrowany.at(x), tablicaSzyfru);
		koordynatyDrugiego = znajdzKoordynatyZnaku(tekstZaszyfrowany.at(x + 1), tablicaSzyfru);

		if (koordynatyPierwszego == nullptr || koordynatyDrugiego == nullptr) {
			cout << "NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy" << endl;
			return "";
		}
		//Pierwszy przypadek
		if (koordynatyPierwszego->x == koordynatyDrugiego->x) {
			//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie wyzej
			//Jesli znak znajduje sie na poczatku kolumny, bierzemy ostatni znak z tej kolumny
			if (koordynatyPierwszego->y - 1 < 0) {
				tekstJawny += tablicaSzyfru[koordynatyPierwszego->x][4];
			}
			else {
				tekstJawny += tablicaSzyfru[koordynatyPierwszego->x][koordynatyPierwszego->y - 1];
			}

			if (koordynatyDrugiego->y - 1 < 0) {
				tekstJawny += tablicaSzyfru[koordynatyDrugiego->x][4];
			}
			else {
				tekstJawny += tablicaSzyfru[koordynatyDrugiego->x][koordynatyDrugiego->y - 1];
			}

			
			
		}
		//Drugi przypadek
		else if (koordynatyPierwszego->y == koordynatyDrugiego->y) {
			//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po lewej
			//Jesli znak znajduje sie na poczatku wiersza, bierzemy ostatni znak z tego wiersza
			if (koordynatyPierwszego->x - 1 < 0) {
				tekstJawny += tablicaSzyfru[4][koordynatyPierwszego->y];
			}
			else {
				tekstJawny += tablicaSzyfru[koordynatyPierwszego->x - 1][koordynatyPierwszego->y];
			}

			if (koordynatyDrugiego->x - 1 < 0) {
				tekstJawny += tablicaSzyfru[4][koordynatyDrugiego->y];
			}
			else {
				tekstJawny += tablicaSzyfru[koordynatyDrugiego->x - 1][koordynatyDrugiego->y];
			}
		}
		//Pozostale przypadki
		else {
			//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
			//przeciecia wiersza drugiego z kolumna pierwszego
			tekstJawny += tablicaSzyfru[koordynatyDrugiego->x][koordynatyPierwszego->y];
			tekstJawny += tablicaSzyfru[koordynatyPierwszego->x][koordynatyDrugiego->y];
		}
	}

	return tekstJawny;
}

void printTab(char tab[5][5]) {
	cout << endl;
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			cout << tab[j][i] << " | ";
		}
		cout << endl;
	}
	cout << endl;
}

point* znajdzKoordynatyZnaku(char znak, char tablica[5][5]) {

	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			if (tablica[j][i] == znak) {
				point* koordynaty = new point;
				koordynaty->x = j;
				koordynaty->y = i;
				return koordynaty;
			}
		}
	}

	return nullptr;
}

Java

package matura;

import java.util.AbstractMap.SimpleEntry;
import java.util.Scanner;

public class Main {
	
	
	private static String prepare(String wyraz) {
		//Usuniecie spacji
		wyraz = wyraz.replaceAll(" ", "");
				
			 
		//Zmiana wszystkich liter na male
		wyraz = wyraz.toLowerCase();
				
			 
		//zamiana liter j na i
		wyraz = wyraz.replaceAll("j", "i");
		
		return wyraz;
	}
	private static String przygotowanieKlucza(String wyraz) {
		if (wyraz.length() == 0) {
			wyraz = "binary";
		}
		return prepare(wyraz);
	}
	
	private static String przygotowanieTekstuJawnego(String wyraz) {
		if (wyraz.length() == 0) {
			wyraz = "programowanie";
		}
		wyraz = prepare(wyraz);
		if(wyraz.length() % 2 != 0) {
			wyraz = wyraz + "z";
		}
		return wyraz;
	}
	 
	
	
	private static void generowanieTablicy(String klucz, char[][] tablicaSzyfru) {
		
		String kontrolny = "";
		String alfabet = "abcdefghiklmnopqrstuvwxyz";

		int x = 0, y = 0;
		int pozycja;

		//Korzystajac z zaawansowanej petli przechodzimy przez kolejne znaki w kluczu
		for (char znak : klucz.toCharArray()) {
			//Sprawdzamy czy dodany znak  znajduje się już w tablicy
			pozycja = kontrolny.indexOf(znak);

			//Jesli nie dodajemy do tablicy i stringa kontrolnego
			if (pozycja == -1) {
				if (y == 5) {
					//Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
					//wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
					System.out.println("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy");
					return;
				}

				//Dodajemy znak do kontrolnego stringa i tablicy
				kontrolny += znak;
				tablicaSzyfru[x][y] = znak;
				x++;

				//Jesli doszlismy do konca wiersza przechodzimy do kolejnego
				if (x == 5) {
					x = 0;
					y++;
				}

			}
		}

		for (char znak : alfabet.toCharArray()) {
			pozycja = kontrolny.indexOf(znak);

			if (pozycja == -1) {
				if (y == 5) {
					System.out.println("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy");
					return;
				}

				kontrolny += znak;
				tablicaSzyfru[x][y] = znak;
				x++;

				if (x == 5) {
					x = 0;
					y++;
				}
			}
		}

		System.out.println("Tablica szyfrowania:");
		printTab(tablicaSzyfru);

	}
	
	
	
	private static void printTab(char[][] tablicaSzyfru) {
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				System.out.print(tablicaSzyfru[j][i] + " | ");
			}
			System.out.println();
		}
	}
	
	
	private static SimpleEntry<Integer, Integer> znajdzKoordynatyZnaku(char znak, char[][] tablica) { //wykorzystujemy istniejaca juz klase SimpleEntry z biblioteki java.util.AbstractMap
		 
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if (tablica[j][i] == znak) {
					SimpleEntry<Integer, Integer> koordynaty = new SimpleEntry<Integer, Integer>(j, i);
					return koordynaty;
				}
			}
		}
		return null;
	}
	
	
	private static String szyfrowanie(String tekstJawny, char[][] tablicaSzyfru) {
		SimpleEntry<Integer, Integer> koordynatyPierwszego;
		SimpleEntry<Integer, Integer> koordynatyDrugiego;
		String tekstZaszyfrowany = "";

		//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
		for (int x = 0; x < tekstJawny.length(); x += 2) {
			//Wyszukiwanie koordynatow obu znakow digrafu
			koordynatyPierwszego = znajdzKoordynatyZnaku(tekstJawny.charAt(x), tablicaSzyfru);
			koordynatyDrugiego = znajdzKoordynatyZnaku(tekstJawny.charAt(x + 1), tablicaSzyfru);

			if (koordynatyPierwszego == null || koordynatyDrugiego == null) {
				System.out.println("NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy");
				return "";
			}

			//Pierwszy przypadek
			if (koordynatyPierwszego.getKey() == koordynatyDrugiego.getKey()) {
				//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
				//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
				//w przypadku znaku bedacego ostatnim znakiem w kolumnie
				tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego.getKey()][(koordynatyPierwszego.getValue() + 1) % 5];
				tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego.getKey()][(koordynatyDrugiego.getValue() + 1) % 5];
			}
			//Drugi przypadek
			else if (koordynatyPierwszego.getValue() == koordynatyDrugiego.getValue() ) {
				//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
				//Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
				//w przypadku znaku bedacym ostatnim znakiem w wierszu
				tekstZaszyfrowany += tablicaSzyfru[(koordynatyPierwszego.getKey() + 1) % 5][koordynatyPierwszego.getValue()];
				tekstZaszyfrowany += tablicaSzyfru[(koordynatyDrugiego.getKey() + 1) % 5][koordynatyDrugiego.getValue()];
			}
			//Pozostale przypadki
			else {
				//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
				//przeciecia wiersza drugiego z kolumna pierwszego
				tekstZaszyfrowany += tablicaSzyfru[koordynatyDrugiego.getKey()][koordynatyPierwszego.getValue()];
				tekstZaszyfrowany += tablicaSzyfru[koordynatyPierwszego.getKey()][koordynatyDrugiego.getValue()];
			}
		}

		return tekstZaszyfrowany;
	}
	
	
	
	
	
	private static String odszyfrowywanie(String tekstZaszyfrowany, char[][] tablicaSzyfru)
	{
		SimpleEntry<Integer, Integer> koordynatyPierwszego;
		SimpleEntry<Integer, Integer> koordynatyDrugiego;
		String tekstJawny = "";
	 
		//Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
		for (int x = 0; x < tekstZaszyfrowany.length(); x += 2) {
			//Wyszukiwanie koordynatow obu znakow digrafu
			koordynatyPierwszego = znajdzKoordynatyZnaku(tekstZaszyfrowany.charAt(x), tablicaSzyfru);
			koordynatyDrugiego = znajdzKoordynatyZnaku(tekstZaszyfrowany.charAt(x + 1), tablicaSzyfru);
	 
			if (koordynatyPierwszego == null || koordynatyDrugiego == null) {
				System.out.println("NIE ZNALEZIONO ZNAKU W TABLICY! - Zakonczenie pracy");
				return "";
			}
			//Pierwszy przypadek
			if (koordynatyPierwszego.getKey() == koordynatyDrugiego.getKey()) {
				//Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie wyzej
				//Jesli znak znajduje sie na poczatku kolumny, bierzemy ostatni znak z tej kolumny
				if (koordynatyPierwszego.getValue() - 1 < 0) {
					tekstJawny += tablicaSzyfru[koordynatyPierwszego.getKey()][4];
				}
				else {
					tekstJawny += tablicaSzyfru[koordynatyPierwszego.getKey()][koordynatyPierwszego.getValue() - 1];
				}
	 
				if (koordynatyDrugiego.getValue() - 1 < 0) {
					tekstJawny += tablicaSzyfru[koordynatyDrugiego.getKey()][4];
				}
				else {
					tekstJawny += tablicaSzyfru[koordynatyDrugiego.getKey()][koordynatyDrugiego.getValue() - 1];
				}
	 
				
				
			}
			//Drugi przypadek
			else if (koordynatyPierwszego.getValue() == koordynatyDrugiego.getValue()) {
				//Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po lewej
				//Jesli znak znajduje sie na poczatku wiersza, bierzemy ostatni znak z tego wiersza
				if (koordynatyPierwszego.getKey() - 1 < 0) {
					tekstJawny += tablicaSzyfru[4][koordynatyPierwszego.getValue()];
				}
				else {
					tekstJawny += tablicaSzyfru[koordynatyPierwszego.getKey() - 1][koordynatyPierwszego.getValue()];
				}
	 
				if (koordynatyDrugiego.getKey() - 1 < 0) {
					tekstJawny += tablicaSzyfru[4][koordynatyDrugiego.getValue()];
				}
				else {
					tekstJawny += tablicaSzyfru[koordynatyDrugiego.getKey() - 1][koordynatyDrugiego.getValue()];
				}
			}
			//Pozostale przypadki
			else {
				//Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
				//przeciecia wiersza drugiego z kolumna pierwszego
				tekstJawny += tablicaSzyfru[koordynatyDrugiego.getKey()][koordynatyPierwszego.getValue()];
				tekstJawny += tablicaSzyfru[koordynatyPierwszego.getKey()][koordynatyDrugiego.getValue()];
			}
		}
	 
		return tekstJawny;
	}
	
	
	public static void main(String[] args){ 
		String tekstJawny = "";
		String klucz = "";
		Scanner sc = new Scanner(System.in);
		System.out.println("Program szyfrujacy metoda PlayFair.");
		System.out.println("Podaj klucz (bez polskich znakow, cyfr i znakow specjalnych):");
		klucz = sc.nextLine();
		System.out.println("Podaj tekst do zaszyfrowania (bez polskich znakow, cyfr i znakow specjalnych):");
		tekstJawny = sc.nextLine();
		System.out.println("Klucz: " + klucz);
		System.out.println("Tekst do szyfrowania: " + tekstJawny);
		klucz = przygotowanieKlucza(klucz);
		tekstJawny = przygotowanieTekstuJawnego(tekstJawny);
		char[][] tab = new char[5][5];
		generowanieTablicy(klucz, tab);
		String tekstZaszyfrowany = szyfrowanie(tekstJawny, tab);
		String tekstOdszyfrowany = odszyfrowywanie(tekstZaszyfrowany, tab);
		System.out.println("Tekst zaszyfrowany: " + tekstZaszyfrowany);
		System.out.println("Tekst odszyfrowany: " + tekstOdszyfrowany);
		sc.close();
	}
	
}

Python

class Point():
    x = 0
    y = 0

    def __init__(self, a, b):
        self.x = a
        self.y = b

def findCoords(znak, tab):
    for i in range(5):
        for j in range(5):
            if tab[j][i] == znak:
                p = Point(j, i)
                return p
    return None

def prepareWord(word):
    word = str(word)
    word = word.replace(" ", "")
    word = word.lower()
    word.replace("j", "i")
    return word

def prepareKey(key):
    if len(key) == 0:
        key = "binary"
    return prepareWord(key)

def prepareText(text):
    if len(text) == 0:
        key = "programowanie"
    text = prepareWord(text)
    if len(text) % 2 != 0:
        text = text + "z"
    return text

def printTab(tab):
    print()
    for x in range(5):
        for y in range(5):
            print(tab[x][y], end=" | ")
        print()
    print()

def generate(key, tab):
    kontrolny = ""
    alfabet = "abcdefghiklmnopqrstuvwxyz"

    x = 0
    y = 0
    pozycja = 0

    for znak in key:  # Korzystajac z petli przechodzimy przez kolejne znaki w kluczu
        pozycja = kontrolny.find(znak)  # Sprawdzamy czy dodany znak  znajduje się już w tablicy
        if pozycja == -1:  # Jesli nie dodajemy do tablicy i stringa kontrolnego
            if y == 5:  # Jesli tekscie jawnym znajduja sie inne znaki oprocz liter
                print("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy")
                return  # wielkosc tablicy zostanie przekroczona - program nie moze wykonac swojego dzialania
            kontrolny += znak
            tab[x][y] = znak
            x += 1
            if x == 5:
                x = 0
                y += 1
    for znak in alfabet:
        pozycja = kontrolny.find(znak)
        if pozycja == -1:
            if y == 5:
                print("BLAD PODCZAS SZYFROWANIA! - Za duza ilosc znakow w tablicy")
                return
            kontrolny += znak
            tab[x][y] = znak
            x += 1
            if x == 5:
                x = 0
                y += 1
    print("Tablica szyfrowania:")
    printTab(tab)

def szyfrowanie(text, tab):
    coordsFirst = Point(0, 0)
    coordsSecond = Point(0, 0)
    encryptedText = ""

    for x in range(0, len(text), 2): #Rozpoczynamy szyfrowanie zakladajac parzysta liczbe znakow w tekscie jawnym
        coordsFirst = findCoords(text[x], tab) #Wyszukiwanie koordynatow obu znakow digrafu
        coordsSecond = findCoords(text[x + 1], tab)

        if coordsFirst == None or coordsSecond == None:
            print("NIE ZNALEZIONO ZNAKU ", text[x],  " W TABLICY! - Zakonczenie pracy")
            return ""

        if coordsFirst.x == coordsSecond.x: #Pierwszy przypadek
            encryptedText += tab[coordsFirst.x][coordsFirst.y + 1] #Jesli znaki sa w tej samej kolumnie zamieniamy je na znaki znajdujace sie nizej
            encryptedText += tab[coordsSecond.x][(coordsSecond.y + 1) % 5] #Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
        else: #Drugi przypadek; Jesli znaki sa w tym samym wierszu zamieniamy je na znaki znajdujace znajdujace sie po prawej
            if coordsFirst.y == coordsSecond.y: #Dzialanie modulo 5 jest potrzebne, aby uchronic sie od wyjscia poza zakres tablicy
                encryptedText += tab[(coordsFirst.x + 1) % 5][coordsFirst.y]
                encryptedText += tab[(coordsSecond.x + 1) % 5][coordsSecond.y]
            else: #Pozostale przypadki
                encryptedText += tab[coordsSecond.x][coordsFirst.y] #Szukamy znakow na przecieciu wiersza znaku pierwszego z kolumna drugiego oraz
                encryptedText += tab[coordsFirst.x][coordsSecond.y] #przeciecia wiersza drugiego z kolumna pierwszego
    return encryptedText

def odszyfrowanie(encrypted, tab):
    first = Point(0, 0)
    second = Point(0, 0)
    finalText = ""
    for x in range(0, len(encrypted), 2):
        first = findCoords(encrypted[x], tab)
        second = findCoords(encrypted[x+1], tab)
        if first == None or second == None:
            print("NIE ZNALEZIONO ZNAKU ", encrypted[x], " W TABLICY! - Zakonczenie pracy")
            return ""
        if first.x == second.x:
            if first.y - 1 < 0:
                finalText += tab[first.x][4]
            else:
                finalText += tab[first.x][first.y-1]
            if second.y - 1 < 0:
                finalText += tab[second.x][4]
            else:
                finalText += tab[second.x][second.y - 1]
        else:
            if first.y == second.y:
                if first.x - 1 < 0:
                    finalText += tab[4][first.x]
                else:
                    finalText += tab[first.x - 1][first.y]
                if second.x - 1 <0:
                    finalText += tab[4][second.y]
                else:
                    finalText += tab[second.x - 1][second.y]
            else:
                finalText += tab[second.x][first.y]
                finalText += tab[first.x][second.y]
    return finalText

print("Program szyfrujacy metoda Playfair")
print("Podaj klucz (bez polskich znakow, cyfr i znakow specjalnych):")
klucz = input()
print("Podaj tekst do zaszyfrowania (bez polskich znakow, cyfr i znakow specjalnych):")
tekstJawny = input()
print("Klucz " + klucz)
print("Tekst do szyfrowania " + tekstJawny)
klucz = prepareKey(klucz)
tekstJawny = prepareText(tekstJawny)
tablica = [[0 for x in range(5)] for y in range(5)]
generate(klucz, tablica)
encrypted = szyfrowanie(tekstJawny, tablica)
print("Tekst zaszyfrowany: " + encrypted)
print("Tekst odszyfrowany: " + odszyfrowanie(encrypted, tablica))

Podsumowanie

Szyfry to zagadnienie ciekawe same w sobie, lecz również przydatne w nauce do matury z informatyki. Jeśli chcecie powiększyć swoją wiedzę informatyczną i przygotować się jak najlepiej do matury, zapraszamy Was do naszej grupy Facebookowej, którą znajdziecie po kliknięciu w poniższą grafikę:

grupa wsparcia matura z informatyki

Chcę wam również pogratulować, ponieważ właśnie poznaliście zasadę działania szyfru Playfaira oraz jego implementację. Dobrnęliście także do końca tego obszernego tekstu. Do zobaczenia niedługo!