/*
 * The program to find the private key of A when his (P, g) parameters and
 * the public keys are given. For testing, the values that are given are 
 * P = 24691, g = 106, Public Key = 12375
 * The logic is that take a counter say count and find the value of
 * x = (g ** count ) mod P
 * for count = 1  till x = 12375
 * The value that is found is the private key of A
 */

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


class DHPrivate{

	/*
	 * Declare all the variables, prime, g, pubKey, priKey
	 */
	BigInteger	prime;
	BigInteger	g;
	BigInteger	pubKey;
	
	/* 
	 * Declare the constructor
	 */
	DHPrivate(BigInteger prime, BigInteger g, BigInteger pubKey)
	 {
		this.prime	= prime;
		this.g		= g;
		this.pubKey	= pubKey;
	 }



	/* 
	 * This function prints the values of various parameters read
	 */
	void Print()
	 {
		System.out.println("The various values are:-");
		System.out.println("Prime No. (P)\t\t: "+prime.toString(10));
		System.out.println("Primary Root (g)\t: " +g.toString(10));
		System.out.println("Public Key\t\t: "+pubKey.toString(10));
	 }


	/* 
	 * This function computes the value of the actual private key using
	 * the prime no. prime, the primary root g and the public key pubKey
	 * The logic is brute force search for the value of the private key
	 */
	void ComputePrivate()
	 {
		BigInteger	count	= new BigInteger("0");
		BigInteger	bigOne	= new BigInteger("1");
		BigInteger	priKey  = new BigInteger("0");
		int		iFlag = 0;


		for(; count.compareTo(prime) == -1; count = count.add(bigOne))
		 {
			if((g.modPow(count, prime)).compareTo(pubKey) == 0)
			 {
				priKey	= count;
				iFlag	= 1;
				break;
			 }
		 }
			
		if(iFlag == 1)
		 {
			System.out.println("Private Key found is\t: "+priKey.toString());
		 }
		else	
		 {
			System.out.println("Private key not found.");
		 }
		 

	 }


	public static void main(String[] args) throws IOException
	 {
		if(args.length != 3)
		 {
			System.out.println("Usage : DHPrivate <PrimeNo> <generator> <PublicKey>");
			System.exit(0);
		 }

		/*
		 * Declare the integer variables to read the command line
		 * arguments and pass them as BigInteger class objects
		 */
		long prime, g, pubKey;
		prime	= Integer.parseInt(args[0]);
		g	= Integer.parseInt(args[1]);
		pubKey	= Integer.parseInt(args[2]);


		DHPrivate dhObj = new DHPrivate(BigInteger.valueOf(prime),
						BigInteger.valueOf(g),
						BigInteger.valueOf(pubKey));

		dhObj.Print();
		dhObj.ComputePrivate();
		return;
	 }
 }


		
		
		

