import java.io.*;
import java.security.*;

/** Program to compute the RSA/DSA signatures of a message
 * Shweta Agrawal
 * 29/8/2003*/

class SignGen
{
	static String msgfile = "";
	static String algo = "";
	static int keysize;
	
	public static void main(String args[])
	{
		
		if(args.length != 3) {
			System.out.println("Usage: SignGen <file_to_sign> <algorithm (DSA/RSA)> <keysize>");
			System.exit(0);
		} else {
			msgfile = args[0];
			algo = args[1];
			keysize = Integer.parseInt(args[2]);
			
			if ( !algo.equals("DSA") && !algo.equals("RSA")) {
				System.out.println("Invalid algorithm");
				System.exit(0);
				}
		}
		
		/** For measuring times */
		long startTime, endTime;
		
		try {

			/** ***************** BEGIN Generate a key pair ****************/
			KeyPairGenerator keygen = KeyPairGenerator.getInstance(algo);
			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 */
			Signature signature = Signature.getInstance("SHA1with" + algo);


			/** ***************** BEGIN Sign the message **************** */
			
			
			/** Initialize for signing with private key*/
			signature.initSign(privatekey);

			startTime = System.currentTimeMillis();
			/** Update the message to be signed */
			FileInputStream fis = new FileInputStream(args[0]);
			BufferedInputStream bis = new BufferedInputStream(fis);
			byte buffer[] = new byte[1024];
			int length;
			while(bis.available() != 0){
				length = bis.read(buffer);
				signature.update(buffer,0,length);
			}
			bis.close();
			fis.close();

			/** Now, that all the data to be signed is read in, 
			and hash generated ( using update method ) generate a 
			signature for it */
			byte[] realsign = signature.sign();

			endTime = System.currentTimeMillis();
			System.out.println("Time to sign = " + (endTime - startTime));

			/** ********************* END Sign the message ************** */
			

			/** ********************* Output to Files ******************* */
			
			/** Save Public key in a file */
			FileOutputStream pubkeyfos = new FileOutputStream(msgfile + "." + algo + "_sign_public_key");
			pubkeyfos.write(publickey.getEncoded());
			pubkeyfos.close();
			//System.out.println("Public key stored in file: " + msgfile + "." + algo + "_sign_public_key");

			/** Save Private key in a file */
			FileOutputStream prikeyfos = new FileOutputStream(msgfile + "." + algo + "_sign_private_key");
			prikeyfos.write(privatekey.getEncoded());
			prikeyfos.close();
			//System.out.println("Public key stored in file: " + msgfile + "." + algo + "_sign_private_key");
			
			/** Save signature in a file */
			FileOutputStream sigfos = new FileOutputStream(msgfile + "." + algo + "_sign");
			sigfos.write(realsign);
			sigfos.close();
			//System.out.println("Signature stored in file: " + msgfile + "." + algo + "_sign");
			
			
			/** ********************* BEGIN verify the signature *********** */
			
			/** Initialize the signature to verify with public key*/
			signature.initVerify(publickey);
			
			startTime = System.currentTimeMillis();
			/** Update the message to be verifed */
			fis = new FileInputStream(args[0]);
			bis = new BufferedInputStream(fis);
			buffer = new byte[1024];
			while(bis.available() != 0){
				length = bis.read(buffer);
				signature.update(buffer,0,length);
			}
			bis.close();
			
			
			/** Verify the signature */
			boolean verified = signature.verify(realsign);
			
			endTime = System.currentTimeMillis();
			//System.out.println("Signature verified to be: "+ verified);
			System.out.println("Time to verify = " + (endTime - startTime));
			

			/** ********************* END verify the signature *********** */
			
			

		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
