Feb 19, 2025

ElGamal Cryptosystem

Decrypt a message from multiple ciphertexts, using shared secrets.

Source Code

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Scanner;

public class ElGamal {
    private BigInteger p, g, x, y;

    public ElGamal(int bitLength) {
        SecureRandom random = new SecureRandom();
        p = BigInteger.probablePrime(bitLength, random);
        g = new BigInteger("2"); // A primitive root modulo p
        x = new BigInteger(bitLength, random).mod(p.subtract(BigInteger.ONE));
        y = g.modPow(x, p);
    }

    public BigInteger[] encrypt(BigInteger message) {
        SecureRandom random = new SecureRandom();
        BigInteger k = new BigInteger(p.bitLength(), random).mod(p.subtract(BigInteger.ONE));
        BigInteger c1 = g.modPow(k, p);
        BigInteger c2 = message.multiply(y.modPow(k, p)).mod(p);
        return new BigInteger[]{c1, c2};
    }

    public BigInteger decrypt(BigInteger[] ciphertext) {
        BigInteger c1 = ciphertext[0];
        BigInteger c2 = ciphertext[1];
        BigInteger s = c1.modPow(x, p);
        return c2.multiply(s.modInverse(p)).mod(p);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ElGamal elGamal = new ElGamal(16);

        System.out.print("Enter message to encrypt: ");
        BigInteger message = scanner.nextBigInteger();

        BigInteger[] ciphertext = elGamal.encrypt(message);
        BigInteger decryptedMessage = elGamal.decrypt(ciphertext);

        System.out.println("Encrypted: " + ciphertext[0] + ", " + ciphertext[1]);
        System.out.println("Decrypted Message: " + decryptedMessage);

        scanner.close();
    }
}