Playfair Substitution Cipher in C#

In my previous article, we discussed Monoalphabetic cipher. Today we present one more substitution cipher technique, Playfair cipher technique. In this cipher method, plaintext splits into multiple units and each unit translate into ciphertext as per Playfair algorithm. The Playfair algorithm uses a 5X5 matrix of letters constructed using a secret key. Let’s have a secret key as “KGYLOPNU”, Playfair alogorithm creates the below pattern table based on secret key “KGYLOPNU”. We have to arrange the secret key first in the matrix. 

K

G

Y

L

O

P

N

U

A

B

C

D

E

F

H

I/J

M

Q

R

S

T

V

W

X

Z

As shown above, first matrix filled by secret key letters and the remaining portion of the matrix occupied by letters in alphabetic order excluding secret key letters. For example, we have letter “K” in the secret key so that it won’t appear it again. That means all letters in the matrix should be unique. I & J counted as one letter, based on programmer wish we can use the letter I or J. There are some rules we have to follow to use Playfair Cipher technique, please find below for the same.

  1. We have to split the message into multiple units, and each unit should contain only two letters.

  2. If any unit contains same letters, those letters should separate with a filler letter ‘x’. For example, if you want to encrypt text “hello” it should be divided into units as ‘he’, ‘lx’, and ‘lo’.

  3. If the plain text unit letters that fall into the same row of the matrix, replaced by the letter to the right. If the letter is the end of the row, it replaced by the first letter of the same row. For example, unit ‘qs’ is encrypted as ‘RI’ or ‘RJ’; we can use I or J for ‘s’.

  4. If the plain text unit letters that fall into the same column will get replaced by the next letter in the same column starts from top to bottom. If the letter is last one, then it will get replaced by the top lettter in the same column. For example, ‘nv’ is encrypted as ‘DG’.

  5. If the text unit fails all of the above conditions (from 2 to 4), each plaintext letter in unit replaced by the letter that lies in the same row and the column occupied by the other plain text letter in the same unit. For example, ‘da’ encrypted as ‘FN’ 

Now we discuss Playfair cipher substitution with an example in C#. Open Microsoft Visual Studio => Create new Console Application and name it as “PlayfairCipherCSharp”, add below code. 

using System;

using System.Linq;

using System.Text.RegularExpressions;

 

namespace PlayfairCipherCSharp

{

    class Program

    {

        static void Main(string[] args)

        {

            string SECRET_KEY = "KGYLOPNU";

 

            Console.WriteLine("Enter your String for Playfair Cipher Encryption:");

            Console.Write("\n");

 

            string sPlainText = Console.ReadLine().ToLower();

            Console.Write("\n");

 

            string sCipherText = PlayfairEncryption(sPlainText, SECRET_KEY);

            Console.WriteLine("Your Cipher Text: " + sCipherText);

            Console.Write("\n");

 

            string sDecryptedPlainText = PlayfairDecryption(sCipherText, SECRET_KEY);

            Console.WriteLine("Your Plain Text: " + sDecryptedPlainText);

            Console.Read();

 

        }

 

        static string PlayfairEncryption(string sInput, string sKey)

        {

            string sEncryptedText = string.Empty;

            if ((sKey != "") && (sInput != ""))

            {

                sKey = sKey.ToLower();

                string sGrid = null;

                string sAlpha = "abcdefghiklmnopqrstuvwxyz";

                sInput = sInput.ToLower();

                string sOutput = "";

                Regex rgx = new Regex("[^a-z-]");

 

                sKey = rgx.Replace(sKey, "");

 

                sKey = sKey.Replace('j', 'i');

 

                for (int i = 0; i < sKey.Length; i++)

                {

                    if ((sGrid == null) || (!sGrid.Contains(sKey[i])))

                    {

                        sGrid += sKey[i];

                    }

                }

 

                for (int i = 0; i < sAlpha.Length; i++)

                {

                    if (!sGrid.Contains(sAlpha[i]))

                    {

                        sGrid += sAlpha[i];

                    }

                }

 

                sInput = rgx.Replace(sInput, "");

 

                sInput = sInput.Replace('j', 'i');

 

                for (int i = 0; i < sInput.Length; i += 2)

                {

                    if (((i + 1) < sInput.Length) && (sInput[i] == sInput[i + 1]))

                    {

                        sInput = sInput.Insert(i + 1, "x");

                    }

                }

 

                if ((sInput.Length % 2) > 0)

                {

                    sInput += "x";

                }

 

                int iTemp = 0;

                do

                {

                    int iPosA = sGrid.IndexOf(sInput[iTemp]);

                    int iPosB = sGrid.IndexOf(sInput[iTemp + 1]);

                    int iRowA = iPosA / 5;

                    int iColA = iPosA % 5;

                    int iRowB = iPosB / 5;

                    int iColB = iPosB % 5;

 

                    if (iColA == iColB)

                    {

                        iPosA += 5;

                        iPosB += 5;

                    }

                    else

                    {

                        if (iRowA == iRowB)

                        {

                            if (iColA == 4)

                            {

                                iPosA -= 4;

                            }

                            else

                            {

                                iPosA += 1;

                            }

                            if (iColB == 4)

                            {

                                iPosB -= 4;

                            }

                            else

                            {

                                iPosB += 1;

                            }

                        }

                        else

                        {

                            if (iRowA < iRowB)

                            {

                                iPosA -= iColA - iColB;

                                iPosB += iColA - iColB;

                            }

                            else

                            {

                                iPosA += iColB - iColA;

                                iPosB -= iColB - iColA;

                            }

                        }

                    }

 

                    if (iPosA >= sGrid.Length)

                    {

                        iPosA = 0 + (iPosA - sGrid.Length);

                    }

 

                    if (iPosB >= sGrid.Length)

                    {

                        iPosB = 0 + (iPosB - sGrid.Length);

                    }

 

                    if (iPosA < 0)

                    {

                        iPosA = sGrid.Length + iPosA;

                    }

 

                    if (iPosB < 0)

                    {

                        iPosB = sGrid.Length + iPosB;

                    }

 

                    sOutput += sGrid[iPosA].ToString() + sGrid[iPosB].ToString();

 

                    iTemp += 2;

                } while (iTemp < sInput.Length);

 

                sEncryptedText = sOutput;

            }

            return sEncryptedText;

        }

 

        static string PlayfairDecryption(string sCipherText, string sKey)

        {

            sKey = sKey.ToLower();

            string sGrid = null;

            string sAlpha = "abcdefghiklmnopqrstuvwxyz";

            string sInput = sCipherText.ToLower();

            string sOutput = "";

 

            sKey = sKey.Replace('j', 'i');

 

            for (int i = 0; i < sKey.Length; i++)

            {

                if ((sGrid == null) || (!sGrid.Contains(sKey[i])))

                {

                    sGrid += sKey[i];

                }

            }

 

            for (int i = 0; i < sAlpha.Length; i++)

            {

                if (!sGrid.Contains(sAlpha[i]))

                {

                    sGrid += sAlpha[i];

                }

            }

 

            int iTemp = 0;

            do

            {

                int iPosA = sGrid.IndexOf(sInput[iTemp]);

                int iPosB = sGrid.IndexOf(sInput[iTemp + 1]);

                int iRowA = iPosA / 5;

                int iColA = iPosA % 5;

                int iRowB = iPosB / 5;

                int iColB = iPosB % 5;

 

                if (iColA == iColB)

                {

                    iPosA -= 5;

                    iPosB -= 5;

                }

                else

                {

                    if (iRowA == iRowB)

                    {

                        if (iColA == 0)

                        {

                            iPosA += 4;

                        }

                        else

                        {

                            iPosA -= 1;

                        }

                        if (iColB == 0)

                        {

                            iPosB += 4;

                        }

                        else

                        {

                            iPosB -= 1;

                        }

                    }

                    else

                    {

                        if (iRowA < iRowB)

                        {

                            iPosA -= iColA - iColB;

                            iPosB += iColA - iColB;

                        }

                        else

                        {

                            iPosA += iColB - iColA;

                            iPosB -= iColB - iColA;

                        }

                    }

                }

 

                if (iPosA > sGrid.Length)

                {

                    iPosA = 0 + (iPosA - sGrid.Length);

                }

 

                if (iPosB > sGrid.Length)

                {

                    iPosB = 0 + (iPosB - sGrid.Length);

                }

 

                if (iPosA < 0)

                {

                    iPosA = sGrid.Length + iPosA;

                }

 

                if (iPosB < 0)

                {

                    iPosB = sGrid.Length + iPosB;

                }

 

                sOutput += sGrid[iPosA].ToString() + sGrid[iPosB].ToString();

 

                iTemp += 2;

            } while (iTemp < sInput.Length);

 

            return sOutput;

        }

    }

} 

As shown above, we are using “KGYLOPNU” as a secret key. Run the application and enter any plain text, it provides the cipher text by applying the Playfair Cipher algorithm. 

The Playfair cipher is more advanced one as compared with Monoalphabetic cipher technique. There are 26X26 = 676 diagrams possible in Playfair cipher. So, it is tough for a hacker to decrypt the cipher text which is encrypted by using Playfair Cipher substitution technique.

 

                                                                      PlayfairCipherCSharp.zip