Skip to content

Commit 9bef5a1

Browse files
authored
Add Playfair Cipher (TheAlgorithms#4988)
1 parent a7d140a commit 9bef5a1

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

DIRECTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* [NonRepeatingNumberFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
2828
* [NumbersDifferentSigns](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
2929
* [ReverseBits](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java)
30+
* [SetKthBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java)
3031
* [SingleBitOperations](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java)
3132
* ciphers
3233
* a5
@@ -44,6 +45,7 @@
4445
* [ColumnarTranspositionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
4546
* [DES](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/DES.java)
4647
* [HillCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/HillCipher.java)
48+
* [PlayfairCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java)
4749
* [Polybius](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Polybius.java)
4850
* [ProductCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
4951
* [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java)
@@ -585,13 +587,15 @@
585587
* [NonRepeatingNumberFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
586588
* [NumbersDifferentSignsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
587589
* [ReverseBitsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/ReverseBitsTest.java)
590+
* [SetKthBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java)
588591
* [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
589592
* ciphers
590593
* a5
591594
* [LFSRTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java)
592595
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
593596
* [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
594597
* [DESTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/DESTest.java)
598+
* [PlayfairTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java)
595599
* [PolybiusTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
596600
* [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java)
597601
* [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.thealgorithms.ciphers;
2+
3+
public class PlayfairCipher {
4+
5+
private char[][] matrix;
6+
private String key;
7+
8+
public PlayfairCipher(String key) {
9+
this.key = key;
10+
generateMatrix();
11+
}
12+
13+
public String encrypt(String plaintext) {
14+
plaintext = prepareText(plaintext.replace("J", "I"));
15+
StringBuilder ciphertext = new StringBuilder();
16+
for (int i = 0; i < plaintext.length(); i += 2) {
17+
char char1 = plaintext.charAt(i);
18+
char char2 = plaintext.charAt(i + 1);
19+
int[] pos1 = findPosition(char1);
20+
int[] pos2 = findPosition(char2);
21+
int row1 = pos1[0];
22+
int col1 = pos1[1];
23+
int row2 = pos2[0];
24+
int col2 = pos2[1];
25+
if (row1 == row2) {
26+
ciphertext.append(matrix[row1][(col1 + 1) % 5]);
27+
ciphertext.append(matrix[row2][(col2 + 1) % 5]);
28+
} else if (col1 == col2) {
29+
ciphertext.append(matrix[(row1 + 1) % 5][col1]);
30+
ciphertext.append(matrix[(row2 + 1) % 5][col2]);
31+
} else {
32+
ciphertext.append(matrix[row1][col2]);
33+
ciphertext.append(matrix[row2][col1]);
34+
}
35+
}
36+
return ciphertext.toString();
37+
}
38+
39+
public String decrypt(String ciphertext) {
40+
StringBuilder plaintext = new StringBuilder();
41+
for (int i = 0; i < ciphertext.length(); i += 2) {
42+
char char1 = ciphertext.charAt(i);
43+
char char2 = ciphertext.charAt(i + 1);
44+
int[] pos1 = findPosition(char1);
45+
int[] pos2 = findPosition(char2);
46+
int row1 = pos1[0];
47+
int col1 = pos1[1];
48+
int row2 = pos2[0];
49+
int col2 = pos2[1];
50+
if (row1 == row2) {
51+
plaintext.append(matrix[row1][(col1 + 4) % 5]);
52+
plaintext.append(matrix[row2][(col2 + 4) % 5]);
53+
} else if (col1 == col2) {
54+
plaintext.append(matrix[(row1 + 4) % 5][col1]);
55+
plaintext.append(matrix[(row2 + 4) % 5][col2]);
56+
} else {
57+
plaintext.append(matrix[row1][col2]);
58+
plaintext.append(matrix[row2][col1]);
59+
}
60+
}
61+
return plaintext.toString();
62+
}
63+
64+
private void generateMatrix() {
65+
String keyWithoutDuplicates = removeDuplicateChars(key + "ABCDEFGHIKLMNOPQRSTUVWXYZ");
66+
matrix = new char[5][5];
67+
int index = 0;
68+
for (int i = 0; i < 5; i++) {
69+
for (int j = 0; j < 5; j++) {
70+
matrix[i][j] = keyWithoutDuplicates.charAt(index);
71+
index++;
72+
}
73+
}
74+
}
75+
76+
private String removeDuplicateChars(String str) {
77+
StringBuilder result = new StringBuilder();
78+
for (int i = 0; i < str.length(); i++) {
79+
if (result.indexOf(String.valueOf(str.charAt(i))) == -1) {
80+
result.append(str.charAt(i));
81+
}
82+
}
83+
return result.toString();
84+
}
85+
86+
private String prepareText(String text) {
87+
text = text.toUpperCase().replaceAll("[^A-Z]", "");
88+
StringBuilder preparedText = new StringBuilder();
89+
char prevChar = '\0';
90+
for (char c : text.toCharArray()) {
91+
if (c != prevChar) {
92+
preparedText.append(c);
93+
prevChar = c;
94+
} else {
95+
preparedText.append('X').append(c);
96+
prevChar = '\0';
97+
}
98+
}
99+
if (preparedText.length() % 2 != 0) {
100+
preparedText.append('X');
101+
}
102+
return preparedText.toString();
103+
}
104+
105+
private int[] findPosition(char c) {
106+
int[] pos = new int[2];
107+
for (int i = 0; i < 5; i++) {
108+
for (int j = 0; j < 5; j++) {
109+
if (matrix[i][j] == c) {
110+
pos[0] = i;
111+
pos[1] = j;
112+
return pos;
113+
}
114+
}
115+
}
116+
return pos;
117+
}
118+
119+
public void printMatrix() {
120+
System.out.println("\nPlayfair Cipher Matrix:");
121+
for (int i = 0; i < 5; i++) {
122+
for (int j = 0; j < 5; j++) {
123+
System.out.print(matrix[i][j] + " ");
124+
}
125+
System.out.println();
126+
}
127+
}
128+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.thealgorithms.ciphers;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
public class PlayfairTest {
8+
9+
@Test
10+
public void testEncryption() {
11+
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
12+
13+
String plaintext = "HELLO";
14+
String encryptedText = playfairCipher.encrypt(plaintext);
15+
assertEquals("GYIZSC", encryptedText);
16+
}
17+
18+
@Test
19+
public void testDecryption() {
20+
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
21+
22+
String encryptedText = "UDRIYP";
23+
String decryptedText = playfairCipher.decrypt(encryptedText);
24+
assertEquals("NEBFVH", decryptedText);
25+
}
26+
27+
@Test
28+
public void testEncryptionAndDecryption() {
29+
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
30+
31+
String plaintext = "PLAYFAIR";
32+
String encryptedText = playfairCipher.encrypt(plaintext);
33+
String decryptedText = playfairCipher.decrypt(encryptedText);
34+
35+
assertEquals(plaintext, decryptedText);
36+
}
37+
}

0 commit comments

Comments
 (0)