# Java Program to implement Playfair Cipher Algorithm

The Playfair Cipher, invented by Charles Wheatstone in 1854, is a classical encryption technique used to secure messages through letter substitution based on a predefined grid· Its simplicity and effectiveness made it popular during historical conflicts like the Boer War and World War I· Implementing classical ciphers such as Playfair in programming languages like Java offers valuable insights into cryptographic principles and historical encryption methods, bridging the gap between traditional and modern encryption techniques·

## Problem Statement:

The goal of this project is to develop a Java program that implements the Playfair Cipher algorithm· The program should allow users to input a custom key and message, encrypting the message according to Playfair Cipher rules· Additionally, the program should handle special cases such as replacing 'J' with 'I', pairing letters, and applying encryption rules based on the constructed Playfair matrix·

### Terminology:

**Plaintext:**It refers to the original message that is intended to be encrypted· It's also commonly known as the message·**Ciphertext:**Ciphertext is the result of encrypting the plaintext message· It's the encrypted form of the original message·**Cipher:**A cipher is an algorithm used for transforming plaintext into ciphertext and vice versa· It's the set of rules and operations applied during encryption and decryption·**Key:**The key is a crucial element in encryption and decryption processes· It's a secret value known only to the sender and receiver· In the context of the Playfair Cipher, the key is used to construct the key-table or key-matrix·**Encipher:**Enciphering is the process of converting plaintext into ciphertext using a specific cipher algorithm and key·**Decipher:**Deciphering is the process of converting ciphertext back into plaintext using the appropriate decryption algorithm and key·**Cryptanalysis:**Cryptanalysis is the study of methods and techniques used to analyze encrypted messages and decipher them without knowledge of the key· It involves understanding the underlying principles of encryption algorithms to break the encryption and reveal the plaintext·

### Advantages of Playfair Cipher:

- Playfair cipher provides a higher level of security compared to simple substitution ciphers due to its use of digraphs·
- The cipher obscures letter frequencies by encrypting letters in pairs, making it harder for attackers to analyze patterns·
- Despite its complexity compared to basic ciphers, Playfair is relatively straightforward to implement and use·
- The size of the key can be varied, offering adaptability and allowing for customization to enhance security·
- Playfair can be applied without the need for computers or advanced technology, making it useful in situations where electronic devices are unavailable·
- Playfair's design allows for easy error correction during decryption, reducing the likelihood of decryption failures·
- Messages encrypted with the Playfair cipher are unreadable without knowledge of the key, ensuring the privacy of communications·
- Playfair cipher has a rich history and was extensively used during certain periods, contributing to its recognition and cultural significance·
- Learning about Playfair cipher introduces students to cryptographic concepts such as substitution and transposition, aiding in the understanding of encryption techniques·
- The Playfair cipher represents an evolutionary step in cryptographic methods, paving the way for more sophisticated encryption techniques used today·

### Limitations of Playfair Cipher:

- Despite its flexibility in key size, the key space of the Playfair cipher is still finite, which can make it vulnerable to brute-force attacks given sufficient computational resources·
- If an attacker has access to the ciphertext and corresponding plaintext pairs, they may be able to deduce parts of the key or encryption algorithm, compromising the security of the cipher·
- The security of the Playfair cipher relies heavily on the secrecy of the key· If the key is compromised, all encrypted messages become vulnerable to decryption·
- Attackers may exploit the predictable nature of the Playfair cipher's encryption process by supplying carefully crafted plaintexts and analyzing the resulting ciphertexts to gain insight into the key or encryption algorithm·
- Playfair's effectiveness can vary depending on the language of the plaintext· For languages with uneven letter frequencies or specific characteristics, the encryption process may be less secure·
- While suitable for manual encryption of short messages, the Playfair cipher becomes increasingly cumbersome for encrypting longer texts, leading to potential errors and decreased security·
- Playfair cipher only provides confidentiality and does not include mechanisms for data integrity or authentication· The leaves encrypted messages vulnerable to tampering or unauthorized modifications·
- Playfair encrypts letters in pairs (digraphs), which can limit its applicability in certain contexts where single-letter encryption is desired or required·
- If the key is compromised at any point, all past and future communications encrypted with that key become susceptible to decryption, lacking the forward secrecy property found in some modern encryption schemes·
- With advancements in cryptanalysis techniques and computing power, the Playfair cipher's security may be insufficient against sophisticated attacks, making it less suitable for contemporary encryption needs·

## Process of Playfair Cipher Algorithm:

### 1. Key Generation:

- The process starts with generating a Playfair matrix based on a given keyword·
- The keyword is first processed to remove any duplicate letters and then used to fill a 5x5 matrix, typically called the Playfair square·
- The remaining letters of the alphabet are then added to the matrix in order, excluding letters already present in the keyword·

### 2. Message Preprocessing:

- The message to be encrypted is prepared for encryption·
- It involves converting the message to uppercase, removing any whitespace, and replacing 'J' with 'I' (as Playfair traditionally does not use 'J')·

### 3. Pairing Letters:

- The message is then processed in pairs of letters·
- If there are consecutive identical letters or an odd number of letters, an 'X' is inserted between them to create pairs·

### 4. Encrypting Pairs:

- For each pair of letters in the message, their positions in the Playfair matrix are determined·
- Depending on their positions in the matrix, the following rules are applied to encrypt the pairs:
- If both letters are in the same row, each letter is replaced by the letter to its right (wrapping around to the leftmost column if necessary)·
- If both letters are in the same column, each letter is replaced by the letter below it (wrapping around to the top row if necessary)·
- If the letters are in different rows and columns, they are replaced by the letters on the same row but at the column of the other letter·

### 5. Creating the Encrypted Message:

- The encrypted pairs are concatenated to form the final encrypted message·

### 6. Decryption:

- To decrypt a message encrypted with the Playfair Cipher, the process is reversed using the same key and matrix·

**Example:**

**Input:**

Enter the key for Playfair Cipher: CHANDU Enter the plaintext to be encipher: PLAYFAIR

**Playfair Cipher Key Matrix:**

C H A N D

U B E F G

I K L M O

P Q R S T

V W X Y Z

**Output:**

Encrypted Message: RINXENLP Decrypted Message: PLAYFAIR

**Explanation:**

Step |
Operation |
Description |

1 | Key Matrix Generation | Generate the Playfair cipher key matrix using the provided key "CHANDU". |

2 | Input Parsing | Parse the plaintext input "PLAYFAIR" to remove any special characters, convert to uppercase, and replace 'J' with 'I'. |

3 | Encryption | Perform encryption on the parsed plaintext using the generated key matrix. |

4 | Decryption | Perform decryption on the encrypted message using the same key matrix. |

**Key Matrix Generation:**

C | H | A | N | D |

U | B | E | F | G |

I/J | K | L | M | O |

P | Q | R | S | T |

V | W | X | Y | Z |

**Input Parsing:**

Parsed plaintext: "PLAYFAIR" (Converted to uppercase, 'J' replaced with 'I')

**Encryption:**

**P and L:**

- P and L are in different rows and columns·
- Encrypt using the positions of P and L: R and N·

2. **A and Y:**

- A and Y are in different rows and columns·
- Encrypt using the positions of A and Y: I and X·

3. **F and R:**

- F and R are in the same row·
- Encrypt using the positions of F and R: N and L·

4. **I and E:**

- I and E are in different rows and columns·
- Encrypt using the positions of I and E: N and L·

5. **R:**

- Add 'X' to make the plaintext length even: R and X·

**Encryption Result:** RINXENLP

**Decryption:**

**R and I:**

- R and I are in different rows and columns·
- Decrypt using the positions of R and I: P and L·

2. **N and X:**

- N and X are in different rows and columns·
- Decrypt using the positions of N and X: A and Y·

3. **E and N:**

- E and N are in the same row·
- Decrypt using the positions of E and N: F and R·

4. **L and R:**

- L and R are in different rows and columns·
- Decrypt using the positions of L and R: I and E·

5. **P and X:**

- P and X are in different rows and columns·
- Decrypt using the positions of P and X: F and R·

**Decryption Result:** PLAYFAIR

**Implementation:**

**FileName:** PlayfairCipher.java

import java.awt.Point; import java.util.Scanner; public class PlayfairCipher { private int length = 0; private String[][] table; public static void main(String args[]) { PlayfairCipher pf = new PlayfairCipher(); } private PlayfairCipher() { // Prompt the user to enter the key for Playfair Cipher System.out.print("Enter the key for Playfair Cipher: "); Scanner sc = new Scanner(System.in); // Parse the input key String key = parseString(sc); while (key.equals("")) key = parseString(sc); // Generate the cipher table based on the key table = this.cipherTable(key); // Prompt the user to enter the plaintext to be enciphered System.out.print("Enter the plaintext to be encipher: "); // Parse the plaintext input String input = parseString(sc); while (input.equals("")) input = parseString(sc); // Perform encryption on the plaintext String output = cipher(input); // Perform decryption on the encrypted message to get the original plaintext String decodedOutput = decode(output); // Display the Playfair Cipher key matrix this.keyTable(table); // Print the encrypted and decrypted messages this.printResults(output, decodedOutput); } // Method to parse input string private String parseString(Scanner sc) { String parse = sc.nextLine(); parse = parse.toUpperCase(); parse = parse.replaceAll("[^A-Z]", ""); parse = parse.replace("J", "I"); return parse; } // Method to generate the cipher table based on the key private String[][] cipherTable(String key) { String[][] playfairTable = new String[5][5]; String keyString = key + "ABCDEFGHIKLMNOPQRSTUVWXYZ"; // Fill the table with empty strings for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { playfairTable[i][j] = ""; } } // Populate the table with characters from the key for (int k = 0; k < keyString.length(); k++) { boolean repeat = false; boolean used = false; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (playfairTable[i][j].equals("" + keyString.charAt(k))) { repeat = true; } else if (playfairTable[i][j].equals("") && !repeat && !used) { playfairTable[i][j] = "" + keyString.charAt(k); used = true; } } } } return playfairTable; } // Method to perform encryption private String cipher(String in) { length = (int) in.length() / 2 + in.length() % 2; // Insert 'X' between double-letter digraphs for (int i = 0; i < (length - 1); i++) { if (in.charAt(2 * i) == in.charAt(2 * i + 1)) { in = new StringBuffer(in).insert(2 * i + 1, 'X').toString(); length = (int) in.length() / 2 + in.length() % 2; } } // Create digraphs String[] digraph = new String[length]; for (int j = 0; j < length; j++) { if (j == (length - 1) && in.length() / 2 == (length - 1)) { in = in + "X"; } digraph[j] = in.charAt(2 * j) + "" + in.charAt(2 * j + 1); } String out = ""; String[] encDigraphs = encodeDigraph(digraph); for (int k = 0; k < length; k++) out = out + encDigraphs[k]; return out; } // Method to encode digraphs private String[] encodeDigraph(String di[]) { String[] encipher = new String[length]; for (int i = 0; i < length; i++) { char a = di[i].charAt(0); char b = di[i].charAt(1); int r1 = (int) getPoint(a).getX(); int r2 = (int) getPoint(b).getX(); int c1 = (int) getPoint(a).getY(); int c2 = (int) getPoint(b).getY(); // Apply encryption rules based on positions in the matrix if (r1 == r2) { c1 = (c1 + 1) % 5; c2 = (c2 + 1) % 5; } else if (c1 == c2) { r1 = (r1 + 1) % 5; r2 = (r2 + 1) % 5; } else { int temp = c1; c1 = c2; c2 = temp; } encipher[i] = table[r1][c1] + "" + table[r2][c2]; } return encipher; } // Method to perform decryption private String decode(String out) { String decoded = ""; for (int i = 0; i < out.length() / 2; i++) { char a = out.charAt(2 * i); char b = out.charAt(2 * i + 1); int r1 = (int) getPoint(a).getX(); int r2 = (int) getPoint(b).getX(); int c1 = (int) getPoint(a).getY(); int c2 = (int) getPoint(b).getY(); // Apply decryption rules based on positions in the matrix if (r1 == r2) { c1 = (c1 + 4) % 5; c2 = (c2 + 4) % 5; } else if (c1 == c2) { r1 = (r1 + 4) % 5; r2 = (r2 + 4) % 5; } else { int temp = c1; c1 = c2; c2 = temp; } decoded = decoded + table[r1][c1] + table[r2][c2]; } return decoded; } // Method to get the position of a character in the matrix private Point getPoint(char c) { Point pt = new Point(0, 0); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (c == table[i][j].charAt(0)) { pt = new Point(i, j); } } } return pt; } // Method to print the key matrix private void keyTable(String[][] printTable) { System.out.println("Playfair Cipher Key Matrix: "); System.out.println(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { System.out.print(printTable[i][j] + " "); } System.out.println(); } System.out.println(); } // Method to print the encrypted and decrypted messages private void printResults(String encipher, String dec) { System.out.print("Encrypted Message: "); System.out.println(encipher); System.out.println(); System.out.print("Decrypted Message: "); System.out.println(dec); } }

**Output:**

Enter the key for Playfair Cipher: CHANDU Enter the plaintext to be encipher: PLAYFAIR Playfair Cipher Key Matrix: C H A N D U B E F G I K L M O P Q R S T V W X Y Z Encrypted Message: RINXENLP Decrypted Message: PLAYFAIR

**Complexity Analysis:**

**Time Complexity:**

- Generating the cipher table: O(1) since the table size is fixed at 5x5·
- Parsing the input string: O(n) where n is the length of the input string·
- Creating digraphs: O(n) where n is the length of the input string·
- Encoding digraphs: O(n) where n is the number of digraphs·
- Decoding: O(n) where n is the number of characters in the encrypted message·

Overall, the time complexity is O(n) where n is the length of the input string or the number of characters in the encrypted message, whichever is greater·

**Space Complexity:**

- Cipher table: O(1) since the table size is fixed at 5x5·
- Digraph array: O(n) where n is the length of the input string·
- Encoded digraphs: O(n) where n is the number of digraphs·
- Decoded output: O(n) where n is the length of the decrypted message·

Overall, the space complexity is O(n) where n is the length of the input string or the number of characters in the encrypted message, whichever is greater·