mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 17:29:31 +08:00
Add Playfair Cipher (#4988)
This commit is contained in:
@ -27,6 +27,7 @@
|
|||||||
* [NonRepeatingNumberFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
|
* [NonRepeatingNumberFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
|
||||||
* [NumbersDifferentSigns](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
|
* [NumbersDifferentSigns](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
|
||||||
* [ReverseBits](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java)
|
* [ReverseBits](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java)
|
||||||
|
* [SetKthBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java)
|
||||||
* [SingleBitOperations](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java)
|
* [SingleBitOperations](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java)
|
||||||
* ciphers
|
* ciphers
|
||||||
* a5
|
* a5
|
||||||
@ -44,6 +45,7 @@
|
|||||||
* [ColumnarTranspositionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
|
* [ColumnarTranspositionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
|
||||||
* [DES](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/DES.java)
|
* [DES](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/DES.java)
|
||||||
* [HillCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/HillCipher.java)
|
* [HillCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/HillCipher.java)
|
||||||
|
* [PlayfairCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java)
|
||||||
* [Polybius](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Polybius.java)
|
* [Polybius](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Polybius.java)
|
||||||
* [ProductCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
|
* [ProductCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
|
||||||
* [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java)
|
* [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java)
|
||||||
@ -585,6 +587,7 @@
|
|||||||
* [NonRepeatingNumberFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
|
* [NonRepeatingNumberFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
|
||||||
* [NumbersDifferentSignsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
|
* [NumbersDifferentSignsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
|
||||||
* [ReverseBitsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/ReverseBitsTest.java)
|
* [ReverseBitsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/ReverseBitsTest.java)
|
||||||
|
* [SetKthBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java)
|
||||||
* [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
|
* [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
|
||||||
* ciphers
|
* ciphers
|
||||||
* a5
|
* a5
|
||||||
@ -592,6 +595,7 @@
|
|||||||
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
|
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
|
||||||
* [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
|
* [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
|
||||||
* [DESTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/DESTest.java)
|
* [DESTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/DESTest.java)
|
||||||
|
* [PlayfairTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java)
|
||||||
* [PolybiusTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
|
* [PolybiusTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
|
||||||
* [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java)
|
* [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java)
|
||||||
* [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
|
* [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
|
||||||
|
128
src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java
Normal file
128
src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
public class PlayfairCipher {
|
||||||
|
|
||||||
|
private char[][] matrix;
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
public PlayfairCipher(String key) {
|
||||||
|
this.key = key;
|
||||||
|
generateMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encrypt(String plaintext) {
|
||||||
|
plaintext = prepareText(plaintext.replace("J", "I"));
|
||||||
|
StringBuilder ciphertext = new StringBuilder();
|
||||||
|
for (int i = 0; i < plaintext.length(); i += 2) {
|
||||||
|
char char1 = plaintext.charAt(i);
|
||||||
|
char char2 = plaintext.charAt(i + 1);
|
||||||
|
int[] pos1 = findPosition(char1);
|
||||||
|
int[] pos2 = findPosition(char2);
|
||||||
|
int row1 = pos1[0];
|
||||||
|
int col1 = pos1[1];
|
||||||
|
int row2 = pos2[0];
|
||||||
|
int col2 = pos2[1];
|
||||||
|
if (row1 == row2) {
|
||||||
|
ciphertext.append(matrix[row1][(col1 + 1) % 5]);
|
||||||
|
ciphertext.append(matrix[row2][(col2 + 1) % 5]);
|
||||||
|
} else if (col1 == col2) {
|
||||||
|
ciphertext.append(matrix[(row1 + 1) % 5][col1]);
|
||||||
|
ciphertext.append(matrix[(row2 + 1) % 5][col2]);
|
||||||
|
} else {
|
||||||
|
ciphertext.append(matrix[row1][col2]);
|
||||||
|
ciphertext.append(matrix[row2][col1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ciphertext.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String decrypt(String ciphertext) {
|
||||||
|
StringBuilder plaintext = new StringBuilder();
|
||||||
|
for (int i = 0; i < ciphertext.length(); i += 2) {
|
||||||
|
char char1 = ciphertext.charAt(i);
|
||||||
|
char char2 = ciphertext.charAt(i + 1);
|
||||||
|
int[] pos1 = findPosition(char1);
|
||||||
|
int[] pos2 = findPosition(char2);
|
||||||
|
int row1 = pos1[0];
|
||||||
|
int col1 = pos1[1];
|
||||||
|
int row2 = pos2[0];
|
||||||
|
int col2 = pos2[1];
|
||||||
|
if (row1 == row2) {
|
||||||
|
plaintext.append(matrix[row1][(col1 + 4) % 5]);
|
||||||
|
plaintext.append(matrix[row2][(col2 + 4) % 5]);
|
||||||
|
} else if (col1 == col2) {
|
||||||
|
plaintext.append(matrix[(row1 + 4) % 5][col1]);
|
||||||
|
plaintext.append(matrix[(row2 + 4) % 5][col2]);
|
||||||
|
} else {
|
||||||
|
plaintext.append(matrix[row1][col2]);
|
||||||
|
plaintext.append(matrix[row2][col1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plaintext.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateMatrix() {
|
||||||
|
String keyWithoutDuplicates = removeDuplicateChars(key + "ABCDEFGHIKLMNOPQRSTUVWXYZ");
|
||||||
|
matrix = new char[5][5];
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
for (int j = 0; j < 5; j++) {
|
||||||
|
matrix[i][j] = keyWithoutDuplicates.charAt(index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String removeDuplicateChars(String str) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
if (result.indexOf(String.valueOf(str.charAt(i))) == -1) {
|
||||||
|
result.append(str.charAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String prepareText(String text) {
|
||||||
|
text = text.toUpperCase().replaceAll("[^A-Z]", "");
|
||||||
|
StringBuilder preparedText = new StringBuilder();
|
||||||
|
char prevChar = '\0';
|
||||||
|
for (char c : text.toCharArray()) {
|
||||||
|
if (c != prevChar) {
|
||||||
|
preparedText.append(c);
|
||||||
|
prevChar = c;
|
||||||
|
} else {
|
||||||
|
preparedText.append('X').append(c);
|
||||||
|
prevChar = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preparedText.length() % 2 != 0) {
|
||||||
|
preparedText.append('X');
|
||||||
|
}
|
||||||
|
return preparedText.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] findPosition(char c) {
|
||||||
|
int[] pos = new int[2];
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
for (int j = 0; j < 5; j++) {
|
||||||
|
if (matrix[i][j] == c) {
|
||||||
|
pos[0] = i;
|
||||||
|
pos[1] = j;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printMatrix() {
|
||||||
|
System.out.println("\nPlayfair Cipher Matrix:");
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
for (int j = 0; j < 5; j++) {
|
||||||
|
System.out.print(matrix[i][j] + " ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
src/test/java/com/thealgorithms/ciphers/PlayfairTest.java
Normal file
37
src/test/java/com/thealgorithms/ciphers/PlayfairTest.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class PlayfairTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncryption() {
|
||||||
|
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
|
||||||
|
|
||||||
|
String plaintext = "HELLO";
|
||||||
|
String encryptedText = playfairCipher.encrypt(plaintext);
|
||||||
|
assertEquals("GYIZSC", encryptedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDecryption() {
|
||||||
|
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
|
||||||
|
|
||||||
|
String encryptedText = "UDRIYP";
|
||||||
|
String decryptedText = playfairCipher.decrypt(encryptedText);
|
||||||
|
assertEquals("NEBFVH", decryptedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncryptionAndDecryption() {
|
||||||
|
PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
|
||||||
|
|
||||||
|
String plaintext = "PLAYFAIR";
|
||||||
|
String encryptedText = playfairCipher.encrypt(plaintext);
|
||||||
|
String decryptedText = playfairCipher.decrypt(encryptedText);
|
||||||
|
|
||||||
|
assertEquals(plaintext, decryptedText);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user