El Gamal encryption of clear Text (not numbers) not woring

934 views Asked by At

Below is my JAVA code for encrypting clear text (not numbers). Code includes both encryption and decryption.

The decrypted text doesn't match clear text, what am I doing work?

My code works if I replace BigInteger m = new BigInteger(msg.getBytes()); with this code BigInteger m = new BigInteger(msg);

package com.porsche.main;

import java.util.*;
import java.math.BigInteger;

public class ElGamal {

    // Get user input for prime.
    // static BigInteger p = new BigInteger("13256401");
    static BigInteger p = new BigInteger("14893003337626352152463254152616458181260144281");
    
    // Calculate a generator.
    // static BigInteger g = new BigInteger("957");
    static BigInteger g = new BigInteger("4893003337626352152463254152616458181260144281");

    // Pick a secret a.
    // BigInteger a = new BigInteger(p.bitCount()-1, r);
    static BigInteger a = new BigInteger("843900337326351225463254152616458181260144281");
    
    public static void main(String[] args) {
    
        Random r = new Random();    
        
        // Calculate the corresponding public b.
        BigInteger b = g.modPow(a, p);
    
        // Print out our public keys.
        System.out.println("p = " + p);
        System.out.println("g = " + g);
        System.out.println("b = " + b);
    
        // When we send a message, the sender picks a random k.
        BigInteger k = new BigInteger(p.bitCount()-1, r);
        
        // Here, the sender starts calculating parts of the cipher text that
        // don't involve the actual message.
        BigInteger c1 = g.modPow(k, p);
        BigInteger c2 = b.modPow(k, p);
    
        // Here we get the message from the user.
        String msg = "12345678901234567890123456789012345678901234567";
        BigInteger m = new BigInteger(msg.getBytes());
        System.out.println("The message encryption = " + msg);
    
        // Now, we can calculate the rest of the second cipher text.
        c2 = c2.multiply(m);
        c2 = c2.mod(p);
    
        // Print out the two cipher texts.
        System.out.println("The corresponding cipher texts are");
        System.out.println("c1 = " + c1);
        System.out.println("c2 = " + c2);
    
        // First, determine the inverse of c1 raised to the a power mod p.
        BigInteger temp = c1.modPow(a,p);
        temp = temporariness(p);

        // Print this out.
        System.out.println("Here is c1^ -a = "+temp);

        // Now, just multiply this by the second cipher text
        BigInteger recover = temp.multiply(c2);
        recover = recover.mod(p);
    
        // And this will give us our original message back!
        System.out.println("The decrypted message = "+recover);
    }
}
1

There are 1 answers

1
Michael Fehr On

You gave very less information about the "El Gamal" algorithm so it is hard to find why your code is not working as expected. Searching a little bit in the net I found a working example code that is very similar to your's and it is working (http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java).

Please keep in mind that working with BigInteger variables mean you will get very large numbers and this is limiting the size of data ("cleartext") you can work with. The sample code has a limit of 19 chars that can be encrypted & decrypted, longer cleartexts won't work. For that reason I used a different cleartext from yours ("9876543210987654321").

The result is here:

El Gamal encryption of clear Text

secretKey = 12345678901234567890
p = 15228497165243954393
b = 3
c = 2082886678951242957
Enter your Big Number message --> Plaintext = 9876543210987654321

Encryption
r = 8874033432052511920
EC = 2442890351962647176
b^r mod p = 8525328674077426405

Decryption
c^r mod p = 11673994647641103379
d = 9011480367194984320
Alice decodes: 9876543210987654321

Thats the working code (minimal changed from the linked one):

import java.math.*;
import java.util.*;
import java.security.*;
import java.io.*;

public class ElGamal2
{
    public static void main(String[] args) throws IOException
    {
        // source http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java
        System.out.println("El Gamal encryption of clear Text\n");
        String msg = "9876543210987654321";
        BigInteger p, b, c, secretKey;
        Random sc = new SecureRandom();
        secretKey = new BigInteger("12345678901234567890");
        //
        // public key calculation
        //
        System.out.println("secretKey = " + secretKey);
        p = BigInteger.probablePrime(64, sc);
        b = new BigInteger("3");
        c = b.modPow(secretKey, p);
        System.out.println("p = " + p);
        System.out.println("b = " + b);
        System.out.println("c = " + c);
        //
        // Encryption
        //
        System.out.print("Enter your Big Number message --> ");
        //String s = Tools.getString();
        String s = msg;
        BigInteger X = new BigInteger(s);
        BigInteger r = new BigInteger(64, sc);
        BigInteger EC = X.multiply(c.modPow(r, p)).mod(p);
        BigInteger brmodp = b.modPow(r, p);
        System.out.println("Plaintext = " + X);
        System.out.println("\nEncryption");
        System.out.println("r = " + r);
        System.out.println("EC = " + EC);
        System.out.println("b^r mod p = " + brmodp);
        //
        // Decryption
        //
        System.out.println("\nDecryption");
        BigInteger crmodp = brmodp.modPow(secretKey, p);
        BigInteger d = crmodp.modInverse(p);
        BigInteger ad = d.multiply(EC).mod(p);
        System.out.println("c^r mod p = " + crmodp);
        System.out.println("d = " + d);
        System.out.println("Alice decodes: " + ad);
    }
}

Edit: Regarding your comment "Thanks for the reply. Does the clear text need to be all numbers only, can it be a text something like "Hellow World!"?":

According to the JavaDocs (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigInteger.html) a BigInteger is created with these constructors and all have one thing in common - it has to be a number that represents a BigInteger-value and that's not a char:

BigInteger​(byte[] val)
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.

BigInteger​(byte[] val, int off, int len)
Translates a byte sub-array containing the two's-complement binary representation of a BigInteger into a BigInteger.

BigInteger​(int signum, byte[] magnitude)
Translates the sign-magnitude representation of a BigInteger into a BigInteger.

BigInteger​(int signum, byte[] magnitude, int off, int len)
Translates the sign-magnitude representation of a BigInteger into a BigInteger.

BigInteger​(int bitLength, int certainty, Random rnd)
Constructs a randomly generated positive BigInteger that is probably prime, with the specified bitLength.

BigInteger​(int numBits, Random rnd)
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2numBits - 1), inclusive.

BigInteger​(String val)
Translates the decimal String representation of a BigInteger into a BigInteger.

BigInteger​(String val, int radix)
Translates the String representation of a BigInteger in the specified radix into a BigInteger.