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

IntroductionThe Playfair CipherRules for EncryptionC ImplementationOutputs for Some PlaintextsFurther Reading
Introduction
The Playfair Cipher
Rules for Encryption
C Implementation
Outputs for Some Plaintexts
Further Reading
Cryptography is the science or art of secret writing. The fundamental objective of cryptography is to enable 2 people to communicate over an insecure channel in such a way that an opponent cannot understand what is being said. There are 2 main types of cryptography in use -
Symmetric key cryptography -when the same key is used for both encryption and decryptionAsymmetric key cryptography -when one key is used for encryption and another for decryption
Symmetric key cryptography -when the same key is used for both encryption and decryption
Asymmetric key cryptography -when one key is used for encryption and another for decryption
There are many other types of ciphers such as monoalphabetic and polyalphabetic, stream and block, etc. This article looks at the Playfair cipher and its application using a C function.
The Playfair cipher, invented by Charles Wheatstone, is a polyalphabetic substitution cipher, meaning that one letter can be denoted by different letters in its encryption, depending on the keyword used, which is given to both parties. For example, let us assume that the keyword is ‘Charles’. 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 plaintext sentence, it is split into digrams, removing all spaces, and padding with the letter x in case of an odd number of letters. Repeating plaintext letters are separated with a filler letter such as x. Given the sentence ‘Meet me at the bridge’, the digrams would be -
me et me at th eb ri dg ex
Two plaintext letters in the same row of the matrix are each replaced by the letter to the right, with the first element of the row circularly following the last.
Two plaintext letters in the same row of the matrix are each replaced by the letter to the right, with the first element of the row circularly following the last.
eb would be replaced by sd
ng would be replaced by gi/gj
2. Two plaintext letters that fall in the same column of the matrix are replaced by the letters beneath, with the top element of the column circularly following the bottom.
dt would be replaced by my
ty would be replaced by yr
3. Otherwise, each plaintext letter in a pair is replaced by the letter that lies in its own row and the column occupied by the other plaintext letter.
me would be replaced by gd
et would be replaced by do
Following these rules, the ciphertext becomes ‘gd do gd rq pr sd hm em bv’.
This cipher is more secure than simple substitution, but is still susceptible to ciphertext-only attacks by doing statistical frequency counts of pairs of letters, since each pair of letters always gets encrypted in the same fashion. Moreover, short keywords make the Playfair cipher even easier to crack.
First we import the required libraries and define a large enough size for allocation of the string to be encrypted.
#include <stdio.h>#include <stdlib.h>#include <string.h> #define SIZE 100
Now we write a function to encrypt a plaintext using the Playfair cipher. The string is converted to upper case and all spaces are removed. The plaintext is padded to an even length and alphabet pairs are made unidentical. 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 plaintext 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, encryption is performed, and the encrypted pair is returned.
// Function to encrypt using the Playfair Ciphervoid PlayfairCrypt(char str[], char keystr[]){    char keyT[5][5], ks, ps;    // Key    ks = strlen(keystr);    // Plaintext    ps = strlen(str);    // Function to convert the string to uppercase    // Can also use the library function toUpper here, but a function was written for better understanding of ascii values.    void toUpperCase(char encrypt[], int ps)    {        int i;        for (i = 0; i < ps; i++) {            if (encrypt[i] > 96 && encrypt[i] < 123)                encrypt[i] -= 32;        }    }    // Function to remove all spaces in a string    int removeSpaces(char* plain, int ps)    {        int i, count = 0;        for (i = 0; i < ps; i++)            if (plain[i] != ' ')                plain[count++] = plain[i];        plain[count] = '\0';        return count;    }    // Function to generate 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;                }            }        }    }    // Function to 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 make the plain text length even, and make pairs unidentical.    int prepare(char str[], int ptrs)    {        int i, j, subs_s = ptrs;        for (i = 0; i < subs_s; i += 2) {            if(str[i]==str[i+1]){                for(j=subs_s; j>i+1; j--){                   str[j]=str[j-1];                }                str[i+1]='x';                subs_s+=1;            }        }        str[subs_s]='\0';        if (subs_s % 2 != 0) {            str[subs_s++] = 'z';            str[subs_s] = '\0';        }        return subs_s;    }    // Function for performing the encryption    void encrypt(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]) {                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]) {                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);    ps = removeSpaces(str, ps);    ps = prepare(str, ps);    generateKeyTable(keystr, ks, keyT);    encrypt(str, keyT, ps);    toUpperCase(str, ps);    //cipher text - printed in upper case letters    printf("Cipher text: %s\n", str);}
The driver code just takes the input key string and input plaintext, and calls the PlayfairCrypt function which outputs the encrypted string.
// Driver codeint main(){    char str[SIZE], keystr[SIZE];    //Key used - to be entered in lower case letters    printf("Enter the key: ");    scanf("%[^\n]s", &keystr);    printf("Key text: %s\n", keystr);    // Plaintext to be encrypted - entered in lower case letters    printf("Enter the plaintext: ");    scanf("\n");    scanf("%[^\n]s", &str);    printf("Plain text: %s\n", str);    //Calling the PlayfairCrypt function    PlayfairCrypt(str, keystr);    return 0;}
The above code is compiled, run and tested for some plaintexts using a key string ‘diskjockey’.
The shipment will arrive at noonLay low until FridayAlways use the back doorThe phone is bugged
The shipment will arrive at noon
Lay low until Friday
Always use the back door
The phone is bugged
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 CipherPlayfair Cipher Decryption
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
Playfair Cipher Decryption