Playfair Cipher Decryption | by Ruthu S Sanketh | Towards Data Science

If you haven’t read this article on Playfair Encryption, go take a look first! It has a brief on the Playfair cipher as well as the logic behind most of the code.
The Playfair CipherRules for DecryptionC ImplementationOutputs for Some CiphertextsFurther Reading
The Playfair Cipher
Rules for Decryption
C Implementation
Outputs for Some Ciphertexts
Further Reading
Assuming the keyword is ‘Charles’, the decryption procedure would be as follows. A 5x5 matrix is drawn, and letters are filled in each cell, starting with the keyword, followed by the letters in the alphabet. I/J are filled in the same cell. All repeating letters are removed, giving us this matrix -
Given a ciphertext sentence, it is split into digrams. For the ciphertext ‘gddogdrqprsdhmembv’, the digrams would be -
gd do gd rq pr sd hm em bv
Two ciphertext letters in the same row of the matrix are each replaced by the letter to the left, with the last element of the row circularly following the first.
Two ciphertext letters in the same row of the matrix are each replaced by the letter to the left, with the last element of the row circularly following the first.
sd would be replaced by eb
gi would be replaced by ng
2. Two ciphertext letters that fall in the same column of the matrix are replaced by the letters above, with the bottom element of the column circularly following the top.
my would be replaced by dt
yr would be replaced by ty
3. Otherwise, each ciphertext letter in a pair is replaced by the letter that lies in its own row and the column occupied by the other ciphertext letter.
gd would be replaced by me
do would be replaced by et
Following these rules, the plaintext becomes ‘Meet me at the bridge’ (x is neglected at the end since its a filler letter).
First we import the required libraries and define a large enough size for allocation of the ciphertext to be decrypted.
#include <stdio.h>#include <stdlib.h>#include <string.h> #define SIZE 100
Now we write a function to decrypt a ciphertext using the Playfair cipher. The string is converted to lower case and the 5x5 key square is generated. For this, first a 26 character hashmap is used to store the count of each alphabet in the key string. Using this, each cell in the matrix is populated with the key string alphabets first, and only once by reducing the count in the hashmap. Then the remaining alphabets are populated.
Each character in the ciphertext is then searched for in the digraph and its position is found. Based on the relative positions of characters in a pair, following the above detailed rules, decryption is performed, and the decrypted pair is returned. Once the digrams are joined, a sentence can be made by looking at the letters and neglecting filler letters like x, etc.
The main difference between the encryption and decryption implementation are the corner cases; when alphabets are in the first row or first column. In the encryption case, alphabets in the last row or last column had to be replaced by those in the first, and this code was taken care of by a modulus 5 operation. However, for decryption, separate if clauses have to be written for these corner cases.
// Function to decrypt using the Playfair Ciphervoid PlayfairDeCrypt(char str[], char keystr[]){	char ps, ks, keyT[5][5];	// Key	ks = strlen(keystr);	// ciphertext	ps = strlen(str);	// Convert all the characters of a string to lowercase	// Can also use the library function toLower here, but a function was written for better understanding of ascii values.	void toLowerCase(char plain[], int ps)	{		int i;		for (i = 0; i < ps; i++) {			if (plain[i] > 64 && plain[i] < 91)				plain[i] += 32;		}	}	// generates the 5x5 key square	void generateKeyTable(char keystr[], int ks,						char keyT[5][5])	{		int i, j, k, flag = 0, *dicty;        // a 26 character hashmap to store count of the alphabet		dicty = (int*)calloc(26, sizeof(int));		for (i = 0; i < ks; i++) {			if (keystr[i] != 'j')				dicty[keystr[i] - 97] = 2;		}		dicty['j' - 97] = 1;		i = 0;		j = 0;		for (k = 0; k < ks; k++) {			if (dicty[keystr[k] - 97] == 2) {				dicty[keystr[k] - 97] -= 1;				keyT[i][j] = keystr[k];				j++;				if (j == 5) {					i++;					j = 0;				}			}		}		for (k = 0; k < 26; k++) {			if (dicty[k] == 0) {				keyT[i][j] = (char)(k + 97);				j++;				if (j == 5) {					i++;					j = 0;				}			}		}	}	// Search for the characters of a digraph in the key square and return their position	void search(char keyT[5][5], char a, char b, int arr[])	{		int i, j;		if (a == 'j')			a = 'i';		else if (b == 'j')			b = 'i';		for (i = 0; i < 5; i++) {			for (j = 0; j < 5; j++) {				if (keyT[i][j] == a) {					arr[0] = i;					arr[1] = j;				}				else if (keyT[i][j] == b) {					arr[2] = i;					arr[3] = j;				}			}		}	}	// Function to decrypt	void decrypt(char str[], char keyT[5][5], int ps)	{		int i, a[4];		for (i = 0; i < ps; i += 2) {			search(keyT, str[i], str[i + 1], a);			if (a[0] == a[2]) {			    if(a[1]==0){			        str[i] = keyT[a[0]][4];			        str[i + 1] = keyT[a[0]][(a[3]-1)%5];			    }			    else if(a[3]==0){			        str[i] = keyT[a[0]][(a[1] - 1)%5];			        str[i + 1] = keyT[a[0]][4];			    }			    else{			        str[i] = keyT[a[0]][(a[1] - 1)%5];			        str[i + 1] = keyT[a[0]][(a[3]-1)%5];			    }			}			else if (a[1] == a[3]) {			    if(a[0]==0){			        str[i] = keyT[4][a[1]];			        str[i + 1] = keyT[(a[2]-1)%5[a[1]];			    }			    else if(a[2]==0){			        str[i] = keyT[(a[0] - 1)%5][a[1]];			        str[i + 1] = keyT[4][a[1]];			    }			    else{			        str[i] = keyT[(a[0] - 1)%5][a[1]];			        str[i + 1] = keyT[(a[2]-1)%5][a[1]];			    }			}			else {				str[i] = keyT[a[0]][a[3]];				str[i + 1] = keyT[a[2]][a[1]];			}		}	}	ks = removeSpaces(keystr, ks);	toLowerCase(str, ps);	ps = removeSpaces(str, ps);	generateKeyTable(keystr, ks, keyT);	decrypt(str, keyT, ps);	//plain text printed in lower case letters	printf("Plain text: %s\n", str);}
The driver code just takes the input key string and input ciphertext, and calls the PlayfairDeCrypt function which outputs the decrypted string.
// Driver codeint main(){	char str[SIZE], keystr[SIZE];	//Key used - to be enered in lower case letters	printf("Enter the key: ");	scanf("%[^\n]s", &keystr);	printf("Key text: %s\n", keystr);	printf("Enter the ciphertext: ");	scanf("\n");	scanf("%[^\n]s", &str);	printf("Cipher text: %s\n", str);	//Calling the PlayfairDeCrypt function	PlayfairDeCrypt(str, keystr);	return 0;}
The above code is compiled, run and tested for some ciphertexts using a key string ‘diskjockey’.
RBIABDIGTPSZREBSLUMNGYXYNBLFCRQTBPCPSCDZLXYBQTDMYIKDTKUFGEQDSIYEITBQGYGDGAKW
RBIABDIGTPSZ
REBSLUMNGYXYNBLFCR
QTBPCPSCDZLXYBQTDMYIKDTKUFGEQDSIYEITBQGYGDGAKW
The entire code used and explained in this article can be found here.
Project -Implementation of the Encoding and Decoding of the Playfair CipherErin Baldwin -An Essay on the Playfair CipherPal, Ramani, Iyengar, Sunitha. A Variation in the Working of the Playfair Cipher
Project -Implementation of the Encoding and Decoding of the Playfair Cipher
Erin Baldwin -An Essay on the Playfair Cipher
Pal, Ramani, Iyengar, Sunitha. A Variation in the Working of the Playfair Cipher