Java Program to Encode a Message Using Playfair Cipher


Encrypting is the task of transforming information into an unreadable format or cipher text. It is usually done to protect the confidentiality of information. There are many ways and algorithms to encrypt data. One such example is the Playfair cipher algorithm. In this article, we are going to see how to write a Java program to encode a message using Playfair cipher.

Playfair cipher makes use of a 5X5 grid or matrix and a set of pre-defined rules. To encrypt, we require a key and the plain text to be encrypted.

Steps

Now let us see the steps to encrypt a message using Playfair cipher −

1. Generate the Key Table

This is the 5x5 grid of alphabets where no repetition is allowed. We start by putting each letter of the key in it followed by all the remaining alphabets. The letters i and j are considered to occupy the same cell in the grid as 5x5 is 25 and there are 26 alphabets in English, hence there would have to be some compromise.

2. Dividing the Plain text into Pairs

If the length of the plaintext is odd, we append the letter X to the end of it to make it even. We then split the entire plain text into pairs i.e. set of 2 letters each. E.g.: if the plain texts are of length 10, there will be 5 pairs of letters.

3. Iterate over the Pairs

For every pair of letters in the plaintext, we do the following −

  • If 2 continuous letters are same then insert an X between them.

  • Find the positions of the 2 letters in the grid created in step 1.

  • If the letters are in the same row, we replace each letter with the letter that is right. In case it is the last element in the row, we can go the first element of the row.

  • If the letters are in the same column, we replace each letter with the letter that is below it. In case it is the last element in the column, we can go the first element of the column.

  • If the letters are not in same column or same row, we replace each letter in the same row but in the column of the other letter.

4. The set of letters obtained after the previous step is the encrypted text.

Now let us see the above implementation in java.

Example

In the below example, we implement Playfair Cipher to Encode a Message.

public class PlayfairCipher {
   private char[][] keyTable;
   private static final int grid_dimension = 5;
   private static final char APPEND = 'X';
   
   public PlayfairCipher(String key) {
      keyTable = generateKeyTable(key);
   }
   
   private char[][] generateKeyTable(String key) {
      // Initialize the key table with all ' ' characters
      char[][] table = new char[grid_dimension][grid_dimension];
      for (int i = 0; i < grid_dimension; i++) {
         for (int j = 0; j < grid_dimension; j++) {
            table[i][j] = ' ';
         }
      }
   
      // Fill the key table with the letters of the key
      int row = 0;
      int col = 0;
      boolean[] used = new boolean[26];
      for (int i = 0; i < key.length(); i++) {
         char ch = Character.toUpperCase(key.charAt(i));
         if (ch == 'J') {
            ch = 'I';
         }
         if (!used[ch - 'A']) {
            table[row][col] = ch;
            used[ch - 'A'] = true;
            col++;
            if (col == grid_dimension) {
               row++;
               col = 0;
            }
         }
      }
      // Fill the remaining cells of the key table with the remaining letters of the alphabet
      for (int i = 0; i < 26; i++) {
         char ch = (char) ('A' + i);
         if (ch == 'J') {
            continue;
         }
         if (!used[i]) {
            table[row][col] = ch;
            col++;
            if (col == grid_dimension) {
               row++;
               col = 0;
            }
         }
      }
   
      return table;
   }
   public String encrypt(String plaintext) {
      plaintext = preprocess(plaintext);
      StringBuilder ciphertext = new StringBuilder();
      for (int i = 0; i < plaintext.length(); i += 2) {
         char ch1 = plaintext.charAt(i);
         char ch2 = plaintext.charAt(i + 1);
         int[] position1 = findPosition(ch1);
         int[] position2 = findPosition(ch2);
         
         if (position1[0] == position2[0]) {
            // When letters exist in same row
            int newCol1 = (position1[1] + 1) % grid_dimension;
            int newCol2 = (position2[1] + 1) % grid_dimension;
            ciphertext.append(keyTable[position1[0]][newCol1]);
            ciphertext.append(keyTable[position2[0]][newCol2]);
         } else if (position1[1] == position2[1]) {
            //  When letters exist in same column
            int newRow1 = (position1[0] + 1) % grid_dimension;
            int newRow2 = (position2[0] + 1) % grid_dimension;
            ciphertext.append(keyTable[newRow1][position1[1]]);
            ciphertext.append(keyTable[newRow2][position2[1]]);
         } else {
            //  When letters are not in the same column or in the same row
            ciphertext.append(keyTable[position1[0]][position2[1]]);
            ciphertext.append(keyTable[position2[0]][position1[1]]);
         }
      }
      return ciphertext.toString();
   }
   public String decrypt(String ciphertext) {
      StringBuilder plaintext = new StringBuilder();
      for (int i = 0; i < ciphertext.length(); i += 2) {
         char ch1 = ciphertext.charAt(i);
         char ch2 = ciphertext.charAt(i + 1);
         int[] position1 = findPosition(ch1);
         int[] position2 = findPosition(ch2);
         if (position1[0] == position2[0]) {
   
            int newCol1 = (position1[1] + grid_dimension - 1) % grid_dimension;
            int newCol2 = (position2[1] + grid_dimension - 1) % grid_dimension;
            plaintext.append(keyTable[position1[0]][newCol1]);
            plaintext.append(keyTable[position2[0]][newCol2]);
         } else if (position1[1] == position2[1]) {
   
            int newRow1 = (position1[0] + grid_dimension - 1) % grid_dimension;
            int newRow2 = (position2[0] + grid_dimension - 1) % grid_dimension;
            plaintext.append(keyTable[newRow1][position1[1]]);
            plaintext.append(keyTable[newRow2][position2[1]]);
         } else {
   
            plaintext.append(keyTable[position1[0]][position2[1]]);
            plaintext.append(keyTable[position2[0]][position1[1]]);
         }
      }
      return postprocess(plaintext.toString());
   }
   private String preprocess(String text) {
      // Replace J with I and add padding if needed
      StringBuilder sb = new StringBuilder(text.toUpperCase().replaceAll("[^A-Z]", ""));
      for (int i = 1; i < sb.length(); i += 2) {
         if (sb.charAt(i) == sb.charAt(i - 1)) {
            sb.insert(i, APPEND);
         }
      }
      if (sb.length() % 2 != 0) {
         sb.append(APPEND);
      }
      return sb.toString();
   }
   private String postprocess(String text) {
      // Remove padding and replace X with the original character
      StringBuilder sb = new StringBuilder(text);
      for (int i = 1; i < sb.length(); i += 2) {
         if (sb.charAt(i) == APPEND) {
            sb.deleteCharAt(i);
         }
      }
      return sb.toString().replace(APPEND, ' ');
   }
   private int[] findPosition(char ch) {
      int[] pos = new int[2];
      for (int i = 0; i < grid_dimension; i++) {
         for (int j = 0; j < grid_dimension; j++) {
            if (keyTable[i][j] == ch) {
               pos[0] = i;
               pos[1] = j;
               return pos;
            }
         }
      }
      return null;
   }
   
   public static void main(String[] args) {
      String plaintext = "MOSQUE";
      String key = "MONARCHY";
      PlayfairCipher cipher = new PlayfairCipher(key);
      String ciphertext = cipher.encrypt(plaintext);
      System.out.println("Plaintext: " + plaintext);
      System.out.println("Ciphertext: " + ciphertext);
      System.out.println("Decrypted text: " + cipher.decrypt(ciphertext));
   }
}

Output

The above program will produce the following output -

Plaintext: MOSQUE
Ciphertext: ONTSML
Decrypted text: MOSQUE

Conclusion

Playfair cipher is a substitution cipher which makes use of a 5x5 grid of letters. It follows a set of if else based rules which leaves no room for ambiguity. It provides a stronger level of security compared to simple substitution cipher. It is easy to understand and implement. Although it has its own set of weaknesses like susceptibility to known plaintext attacks and its key management issues and inability to encrypt characters which are not letters, it is an interesting and historical example of symmetric encryption algorithm. It is no longer used to establish real life secure communication but provides a great understanding of basic concepts and techniques used in modern day encryption algorithms.

Updated on: 10-Mar-2023

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements