Skip to content

Commit 1dbcd48

Browse files
committed
Fix checkstyle violations: remove trailing spaces and add utility class constructor
1 parent 4dc2c6c commit 1dbcd48

File tree

1 file changed

+48
-48
lines changed

1 file changed

+48
-48
lines changed

src/main/java/com/thealgorithms/ciphers/ElGamalCipher.java

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66

77
/**
88
* ElGamal Encryption Algorithm Implementation
9-
*
9+
*
1010
* ElGamal is an asymmetric key encryption algorithm for public-key cryptography
1111
* based on the Discrete Logarithm Problem (DLP). It provides semantic security
1212
* through randomization in the encryption process.
13-
*
13+
*
1414
* Key Components:
1515
* - p: Large prime number (modulus)
1616
* - g: Generator of the multiplicative group modulo p
1717
* - x: Private key (random integer)
1818
* - y: Public key where y = g^x mod p
19-
*
19+
*
2020
* Encryption: For message m, choose random k and compute:
2121
* c1 = g^k mod p
2222
* c2 = m * y^k mod p
2323
* Ciphertext = (c1, c2)
24-
*
24+
*
2525
* Decryption: Recover m using:
2626
* m = c2 * (c1^x)^-1 mod p
2727
* where (c1^x)^-1 is the modular multiplicative inverse
28-
*
28+
*
2929
* @author TheAlgorithms
3030
*/
3131
public final class ElGamalCipher {
@@ -95,42 +95,42 @@ public String toString() {
9595

9696
/**
9797
* Generates ElGamal key pair with specified bit length
98-
*
98+
*
9999
* Steps:
100100
* 1. Generate a large prime p
101101
* 2. Find a generator g of the multiplicative group mod p
102102
* 3. Choose random private key x in range [2, p-2]
103103
* 4. Compute public key y = g^x mod p
104-
*
104+
*
105105
* @param bitLength The bit length for the prime (e.g., 512, 1024, 2048)
106106
* @return KeyPair containing (p, g, x, y)
107107
*/
108108
public static KeyPair generateKeys(int bitLength) {
109109
SecureRandom random = new SecureRandom();
110-
110+
111111
// Generate a large prime p
112112
BigInteger p = BigInteger.probablePrime(bitLength, random);
113-
113+
114114
// Find a generator g (simplified: use a small generator that works for most primes)
115115
// In practice, we often use g = 2 or find a primitive root
116116
BigInteger g = findGenerator(p, random);
117-
117+
118118
// Generate private key x: random number in range [2, p-2]
119119
BigInteger x;
120120
do {
121121
x = new BigInteger(bitLength - 1, random);
122122
} while (x.compareTo(BigInteger.TWO) < 0 || x.compareTo(p.subtract(BigInteger.TWO)) > 0);
123-
123+
124124
// Calculate public key y = g^x mod p
125125
BigInteger y = g.modPow(x, p);
126-
126+
127127
return new KeyPair(p, g, x, y);
128128
}
129129

130130
/**
131131
* Finds a generator for the multiplicative group modulo p
132132
* Simplified approach: tries small values until finding a suitable generator
133-
*
133+
*
134134
* @param p The prime modulus
135135
* @param random Random number generator
136136
* @return A generator g
@@ -139,7 +139,7 @@ private static BigInteger findGenerator(BigInteger p, Random random) {
139139
// Simplified: use 2 as generator (works for most safe primes)
140140
// For production, should verify g is a primitive root
141141
BigInteger g = BigInteger.valueOf(2);
142-
142+
143143
// If 2 doesn't work, try other small values
144144
while (g.compareTo(p) < 0) {
145145
// Check if g is a valid generator (simplified check)
@@ -148,22 +148,22 @@ private static BigInteger findGenerator(BigInteger p, Random random) {
148148
}
149149
g = g.add(BigInteger.ONE);
150150
}
151-
151+
152152
return BigInteger.valueOf(2); // Fallback
153153
}
154154

155155
/**
156156
* Encrypts a message using ElGamal encryption
157-
*
157+
*
158158
* Process:
159159
* 1. Choose random k in range [2, p-2]
160160
* 2. Compute c1 = g^k mod p
161161
* 3. Compute c2 = m * y^k mod p
162162
* 4. Return ciphertext (c1, c2)
163-
*
163+
*
164164
* The random k ensures semantic security - same message encrypted
165165
* multiple times produces different ciphertexts
166-
*
166+
*
167167
* @param message The plaintext message as BigInteger (must be < p)
168168
* @param keyPair The key pair containing public parameters
169169
* @return Ciphertext (c1, c2)
@@ -172,40 +172,40 @@ public static Ciphertext encrypt(BigInteger message, KeyPair keyPair) {
172172
if (message.compareTo(keyPair.getP()) >= 0) {
173173
throw new IllegalArgumentException("Message must be less than modulus p");
174174
}
175-
175+
176176
SecureRandom random = new SecureRandom();
177177
BigInteger p = keyPair.getP();
178178
BigInteger g = keyPair.getG();
179179
BigInteger y = keyPair.getPublicKey();
180-
180+
181181
// Choose random k in range [2, p-2]
182182
BigInteger k;
183183
do {
184184
k = new BigInteger(p.bitLength() - 1, random);
185185
} while (k.compareTo(BigInteger.TWO) < 0 || k.compareTo(p.subtract(BigInteger.TWO)) > 0);
186-
186+
187187
// Compute c1 = g^k mod p
188188
BigInteger c1 = g.modPow(k, p);
189-
189+
190190
// Compute c2 = m * y^k mod p
191191
BigInteger c2 = message.multiply(y.modPow(k, p)).mod(p);
192-
192+
193193
return new Ciphertext(c1, c2);
194194
}
195195

196196
/**
197197
* Decrypts a ciphertext using ElGamal decryption
198-
*
198+
*
199199
* Process:
200200
* 1. Compute s = c1^x mod p (shared secret)
201201
* 2. Compute s^-1 (modular multiplicative inverse of s)
202202
* 3. Recover m = c2 * s^-1 mod p
203-
*
203+
*
204204
* Mathematical proof:
205205
* c2 * (c1^x)^-1 = (m * y^k) * (g^(k*x))^-1
206206
* = (m * g^(k*x)) * (g^(k*x))^-1
207207
* = m
208-
*
208+
*
209209
* @param ciphertext The ciphertext (c1, c2)
210210
* @param keyPair The key pair containing private key
211211
* @return Decrypted plaintext message
@@ -215,22 +215,22 @@ public static BigInteger decrypt(Ciphertext ciphertext, KeyPair keyPair) {
215215
BigInteger c2 = ciphertext.getC2();
216216
BigInteger x = keyPair.getPrivateKey();
217217
BigInteger p = keyPair.getP();
218-
218+
219219
// Compute s = c1^x mod p
220220
BigInteger s = c1.modPow(x, p);
221-
221+
222222
// Compute s^-1 mod p (modular multiplicative inverse)
223223
BigInteger sInverse = s.modInverse(p);
224-
224+
225225
// Recover message: m = c2 * s^-1 mod p
226226
BigInteger message = c2.multiply(sInverse).mod(p);
227-
227+
228228
return message;
229229
}
230230

231231
/**
232232
* Converts a string to BigInteger for encryption
233-
*
233+
*
234234
* @param text The input string
235235
* @return BigInteger representation
236236
*/
@@ -241,7 +241,7 @@ public static BigInteger stringToBigInteger(String text) {
241241

242242
/**
243243
* Converts BigInteger back to string after decryption
244-
*
244+
*
245245
* @param number The BigInteger to convert
246246
* @return Original string
247247
*/
@@ -261,65 +261,65 @@ public static String bigIntegerToString(BigInteger number) {
261261
*/
262262
public static void main(String[] args) {
263263
System.out.println("=== ElGamal Encryption Algorithm Demo ===\n");
264-
264+
265265
// Example 1: Encrypting a small integer
266266
System.out.println("Example 1: Encrypting a small integer");
267267
System.out.println("--------------------------------------");
268-
268+
269269
// Generate keys with 512-bit prime (use 1024 or 2048 for production)
270270
System.out.println("Generating keys (512-bit)...");
271271
KeyPair keyPair = generateKeys(512);
272-
272+
273273
System.out.println("Prime (p): " + keyPair.getP());
274274
System.out.println("Generator (g): " + keyPair.getG());
275275
System.out.println("Private key (x): " + keyPair.getPrivateKey());
276276
System.out.println("Public key (y): " + keyPair.getPublicKey());
277-
277+
278278
// Message to encrypt
279279
BigInteger message = BigInteger.valueOf(12345);
280280
System.out.println("\nOriginal message: " + message);
281-
281+
282282
// Encrypt
283283
Ciphertext ciphertext = encrypt(message, keyPair);
284284
System.out.println("Encrypted: " + ciphertext);
285-
285+
286286
// Decrypt
287287
BigInteger decrypted = decrypt(ciphertext, keyPair);
288288
System.out.println("Decrypted message: " + decrypted);
289-
289+
290290
// Verify
291291
System.out.println("Decryption successful: " + message.equals(decrypted));
292-
292+
293293
// Example 2: Demonstrating semantic security
294294
System.out.println("\n\nExample 2: Demonstrating Semantic Security");
295295
System.out.println("------------------------------------------");
296296
System.out.println("Same message encrypted twice produces different ciphertexts:");
297-
297+
298298
Ciphertext ct1 = encrypt(message, keyPair);
299299
Ciphertext ct2 = encrypt(message, keyPair);
300-
300+
301301
System.out.println("Encryption 1: " + ct1);
302302
System.out.println("Encryption 2: " + ct2);
303303
System.out.println("Are ciphertexts different? " + !ct1.getC1().equals(ct2.getC1()));
304-
304+
305305
// Both decrypt to same message
306306
System.out.println("Both decrypt to: " + decrypt(ct1, keyPair) + " and " + decrypt(ct2, keyPair));
307-
307+
308308
// Example 3: String encryption
309309
System.out.println("\n\nExample 3: Encrypting a String");
310310
System.out.println("-------------------------------");
311-
311+
312312
String text = "Hello";
313313
System.out.println("Original text: " + text);
314-
314+
315315
BigInteger textAsNumber = stringToBigInteger(text);
316316
System.out.println("Text as BigInteger: " + textAsNumber);
317-
317+
318318
// Check if message is small enough
319319
if (textAsNumber.compareTo(keyPair.getP()) < 0) {
320320
Ciphertext textCiphertext = encrypt(textAsNumber, keyPair);
321321
System.out.println("Encrypted: " + textCiphertext);
322-
322+
323323
BigInteger decryptedNumber = decrypt(textCiphertext, keyPair);
324324
String decryptedText = bigIntegerToString(decryptedNumber);
325325
System.out.println("Decrypted text: " + decryptedText);

0 commit comments

Comments
 (0)