mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 01:35:16 +08:00
Add DiffieHellman and MonoAlphabetic (#5508)
This commit is contained in:
36
src/main/java/com/thealgorithms/ciphers/DiffieHellman.java
Normal file
36
src/main/java/com/thealgorithms/ciphers/DiffieHellman.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public final class DiffieHellman {
|
||||||
|
|
||||||
|
private final BigInteger base;
|
||||||
|
private final BigInteger secret;
|
||||||
|
private final BigInteger prime;
|
||||||
|
|
||||||
|
// Constructor to initialize base, secret, and prime
|
||||||
|
public DiffieHellman(BigInteger base, BigInteger secret, BigInteger prime) {
|
||||||
|
// Check for non-null and positive values
|
||||||
|
if (base == null || secret == null || prime == null || base.signum() <= 0 || secret.signum() <= 0 || prime.signum() <= 0) {
|
||||||
|
throw new IllegalArgumentException("Base, secret, and prime must be non-null and positive values.");
|
||||||
|
}
|
||||||
|
this.base = base;
|
||||||
|
this.secret = secret;
|
||||||
|
this.prime = prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to calculate public value (g^x mod p)
|
||||||
|
public BigInteger calculatePublicValue() {
|
||||||
|
// Returns g^x mod p
|
||||||
|
return base.modPow(secret, prime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to calculate the shared secret key (otherPublic^secret mod p)
|
||||||
|
public BigInteger calculateSharedSecret(BigInteger otherPublicValue) {
|
||||||
|
if (otherPublicValue == null || otherPublicValue.signum() <= 0) {
|
||||||
|
throw new IllegalArgumentException("Other public value must be non-null and positive.");
|
||||||
|
}
|
||||||
|
// Returns b^x mod p or a^y mod p
|
||||||
|
return otherPublicValue.modPow(secret, prime);
|
||||||
|
}
|
||||||
|
}
|
48
src/main/java/com/thealgorithms/ciphers/MonoAlphabetic.java
Normal file
48
src/main/java/com/thealgorithms/ciphers/MonoAlphabetic.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
public final class MonoAlphabetic {
|
||||||
|
|
||||||
|
private MonoAlphabetic() {
|
||||||
|
throw new UnsupportedOperationException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encryption method
|
||||||
|
public static String encrypt(String data, String key) {
|
||||||
|
if (!data.matches("[A-Z]+")) {
|
||||||
|
throw new IllegalArgumentException("Input data contains invalid characters. Only uppercase A-Z are allowed.");
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// Encrypt each character
|
||||||
|
for (char c : data.toCharArray()) {
|
||||||
|
int idx = charToPos(c); // Get the index of the character
|
||||||
|
sb.append(key.charAt(idx)); // Map to the corresponding character in the key
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decryption method
|
||||||
|
public static String decrypt(String data, String key) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// Decrypt each character
|
||||||
|
for (char c : data.toCharArray()) {
|
||||||
|
int idx = key.indexOf(c); // Find the index of the character in the key
|
||||||
|
if (idx == -1) {
|
||||||
|
throw new IllegalArgumentException("Input data contains invalid characters.");
|
||||||
|
}
|
||||||
|
sb.append(posToChar(idx)); // Convert the index back to the original character
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method: Convert a character to its position in the alphabet
|
||||||
|
private static int charToPos(char c) {
|
||||||
|
return c - 'A'; // Subtract 'A' to get position (0 for A, 1 for B, etc.)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method: Convert a position in the alphabet to a character
|
||||||
|
private static char posToChar(int pos) {
|
||||||
|
return (char) (pos + 'A'); // Add 'A' to convert position back to character
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
public class DiffieHellmanTest {
|
||||||
|
|
||||||
|
// Test for public value calculation using instance methods
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("provideTestData")
|
||||||
|
public void testCalculatePublicValue(BigInteger base, BigInteger secret, BigInteger prime, BigInteger publicExpected, BigInteger sharedExpected) {
|
||||||
|
DiffieHellman dh = new DiffieHellman(base, secret, prime); // Create an instance of DiffieHellman
|
||||||
|
assertEquals(publicExpected, dh.calculatePublicValue()); // Call instance method
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for shared secret calculation using instance methods
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("provideTestData")
|
||||||
|
public void testCalculateSharedSecret(BigInteger base, BigInteger secret, BigInteger prime, BigInteger publicExpected, BigInteger sharedExpected) {
|
||||||
|
DiffieHellman dh = new DiffieHellman(base, secret, prime); // Create an instance of DiffieHellman
|
||||||
|
assertEquals(sharedExpected, dh.calculateSharedSecret(publicExpected)); // Call instance method
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide test data for both public key and shared secret calculation
|
||||||
|
private static Stream<Arguments> provideTestData() {
|
||||||
|
return Stream.of(createTestArgs(5, 6, 23, 8, 13), createTestArgs(2, 5, 13, 6, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for arguments
|
||||||
|
private static Arguments createTestArgs(long base, long secret, long prime, long publicExpected, long sharedExpected) {
|
||||||
|
return Arguments.of(BigInteger.valueOf(base), BigInteger.valueOf(secret), BigInteger.valueOf(prime), BigInteger.valueOf(publicExpected), BigInteger.valueOf(sharedExpected));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.thealgorithms.ciphers;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
public class MonoAlphabeticTest {
|
||||||
|
|
||||||
|
// Test for both encryption and decryption with different keys
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("provideTestData")
|
||||||
|
public void testEncryptDecrypt(String plainText, String key, String encryptedText) {
|
||||||
|
// Test encryption
|
||||||
|
String actualEncrypted = MonoAlphabetic.encrypt(plainText, key);
|
||||||
|
assertEquals(encryptedText, actualEncrypted, "Encryption failed for input: " + plainText + " with key: " + key);
|
||||||
|
|
||||||
|
// Test decryption
|
||||||
|
String actualDecrypted = MonoAlphabetic.decrypt(encryptedText, key);
|
||||||
|
assertEquals(plainText, actualDecrypted, "Decryption failed for input: " + encryptedText + " with key: " + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide test data for both encryption and decryption
|
||||||
|
private static Stream<Arguments> provideTestData() {
|
||||||
|
return Stream.of(Arguments.of("HELLO", "MNBVCXZLKJHGFDSAPOIUYTREWQ", "LCGGS"), Arguments.of("JAVA", "MNBVCXZLKJHGFDSAPOIUYTREWQ", "JMTM"), Arguments.of("HELLO", "QWERTYUIOPLKJHGFDSAZXCVBNM", "ITKKG"), Arguments.of("JAVA", "QWERTYUIOPLKJHGFDSAZXCVBNM", "PQCQ"));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user