/*
 * This is the program to find signatures and the time to find the signature
 * and verify the signature. The usage is 
 * java RSADSASignGen <AlgoName> <AlgoPRNG> <filename> <msgsize> <keysize>
 * The AlgoName is the algorithm to use i.e. RSA or DSA and correspondingly
 * the method AlgoPRNG to be used for finding pseudo random nos.
 */


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

class RSADSASignGen
{
	String strAlgo;				/**Algo Name	*/
	String strFilename;			/**Filename	*/
	String strPRNG;				/**Algo for PRNG*/

	
	int    keySize;
	int    msgSize;

	/**Variable to hold the digest */
	byte   hash[];				

	/**
	 * The various variables to store the time values
	 */
	long   timeStart;
	long   timeEnd;
	long   timeTotalGen;
	long   timeTotalVerify;

	/**
	 * Constructor
	 */
	public RSADSASignGen(String args[])
	 {
		strAlgo		= new String(args[0]);
		strPRNG		= new String(args[1]);
		strFilename	= new String(args[2]);
		msgSize		= Integer.parseInt(args[3]);
		keySize		= Integer.parseInt(args[4]);
	 }

	public long getCurrentTime()
	 {
		return Calendar.getInstance().getTimeInMillis();
	 }



		
	void Generate() throws IOException, NoSuchAlgorithmException,SignatureException, InvalidKeyException
	 {
		byte buffer[]	= new byte[10000];
		byte[] realsign;
		int length;


		timeStart		= getCurrentTime();
		
		/************* BEGIN Generate a key pair **************/
		KeyPairGenerator keygen = KeyPairGenerator.getInstance(strAlgo);
		SecureRandom random	= SecureRandom.getInstance("SHA1PRNG");

		keygen.initialize(keySize,random);

		KeyPair keypair		= keygen.generateKeyPair();
		PrivateKey privatekey	= keypair.getPrivate();
		PublicKey publickey	= keypair.getPublic();
		/*********** END Generate a key pair ******************/

		/**Create a Signature object and initialize it with pvt key*/
		Signature rsadsa	= Signature.getInstance(strPRNG);
		rsadsa.initSign(privatekey);

		/********* Update and Sign the data *******************/
		FileInputStream fis	= new FileInputStream(strFilename);
		BufferedInputStream bis	= new BufferedInputStream(fis);

		length	= bis.read(buffer, 0, msgSize);
		System.out.println("Msg : "+length);
		rsadsa.update(buffer,0,length);
		bis.close();



		/*
		 * Now, that all the data to be signed is read in,
		 * and hash generated ( using update method )
		 * generate a signature for it
		 */
		realsign = rsadsa.sign();
		/** All the events habve occured, take the end timestamp*/
		timeEnd			= getCurrentTime();
		timeTotalGen		= timeEnd - timeStart;
		/*********** Save signature in a file *************/
		FileOutputStream sigfos = new FileOutputStream(strFilename+"."+strAlgo+"."+strPRNG+".sign");
		sigfos.write(realsign);
		sigfos.close();


		/*
		 *  Verification of the signature
		 */
		Signature sig	= Signature.getInstance(strPRNG);

		/** Take the staring timestamp for verification	*/
		timeStart	= getCurrentTime();
		sig.initVerify(publickey);
		sig.update(buffer,0,length);
		boolean boolVerify = sig.verify(realsign);
		/**Take the end time of the verification	*/
		timeEnd		= getCurrentTime();
		timeTotalVerify	= timeEnd - timeStart;



		/*********** Save Public key in a file *************/
		FileOutputStream pubkeyfos = new FileOutputStream(strFilename+"."+strAlgo+"."+strPRNG+".dsa_sign_public_key");
		pubkeyfos.write(publickey.getEncoded());
		pubkeyfos.close();




		/*********** Save Private key in a file *************/
		FileOutputStream prikeyfos = new FileOutputStream(strFilename+"."+strAlgo+"."+strPRNG+".dsa_sign_private_key");
		prikeyfos.write(privatekey.getEncoded());
	 }


	/**
	 * Output the various values
	 */
	void WriteStat()
	 {
		/*
		 * The fields that need to be printed are 
		 * Message Size, Key Size and the algorithm used
		 */

		System.out.println(msgSize + "\t\t" + keySize + "\t\t" + 
				strAlgo + "\t" + strPRNG + "\t" + timeTotalGen +"\t\t"+timeTotalVerify);
		
	 }



	public static void main(String args[]) throws IOException,NoSuchAlgorithmException, SignatureException, InvalidKeyException
	{
		if(args.length!=5){
			System.out.println("Usage: DSASignGen <Algo> <PRNG> <name_of_file_to_sign> <messagesize> <keysize>");
			System.exit(0);
		}

		RSADSASignGen rsadsaGen	= new RSADSASignGen(args);
		/** Generate the signature and output the values*/ 
		rsadsaGen.Generate();
		rsadsaGen.WriteStat();
	 }
}


