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

class RSASignGen
{

	public static long getCurrentTime()
	{
		java.util.Date date=Calendar.getInstance().getTime();
		Timestamp a=new Timestamp(date.getTime());
		long currentTime=Calendar.getInstance().getTimeInMillis();
		System.out.println("Time: "+currentTime);
		return currentTime;
	}


	public static void main(String args[])
	{
		if(args.length!=1){
			System.out.println("Usage: RSASignGen <name_of_file_to_sign>");
			System.exit(0);
		}
		try{


			/************************* Calculate digest of the message ***************************/
			System.out.println("Starting time is ");
			long start=getCurrentTime();

			MessageDigest md = MessageDigest.getInstance("SHA-1");

			FileInputStream fis1 = new FileInputStream(args[0]);
			BufferedInputStream bis1 = new BufferedInputStream(fis1);
			byte buffer1[] = new byte[1024];
			int length1;
                        while(bis1.available() != 0){
                                length1 = bis1.read(buffer1);
                                md.update(buffer1,0,length1);
                        }
                        bis1.close();

			byte[] digest = md.digest();

			System.out.println("Calculation of digest of a message completed at");
			long end=getCurrentTime();
			System.out.println("Total elapsed time in ms= "+(end-start));
		
			FileOutputStream mdfos = new FileOutputStream(args[0]+".md");
                        mdfos.write(digest);
                        mdfos.close();

			/************************* BEGIN Generate a key pair ***************************/
			KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG","SUN");

			keygen.initialize(1024,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 private key **************/
			System.out.println("Starting time is ");
                        long start1=getCurrentTime();

			Signature rsa = Signature.getInstance("SHA1withRSA");
			rsa.initSign(privatekey);

			/************************* Update and Sign the data ***************************/
			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);
				rsa.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
			 */
			byte[] realsign = rsa.sign();

			System.out.println("Signing of a message completed at");
			long end1=getCurrentTime();
			System.out.println("Total elapsed time in ms= "+(end1-start1));
			

			/************************* Verify the signature ***************************/
			System.out.println("Starting time is ");
                        long start2=getCurrentTime();

			rsa.initVerify(publickey);
			FileInputStream fis2 = new FileInputStream(args[0]);
                        BufferedInputStream bis2 = new BufferedInputStream(fis2);
                        byte buffer2[] = new byte[1024];
                        int length2;
                        while(bis2.available() != 0){
                                length2 = bis2.read(buffer2);
                                rsa.update(buffer2,0,length2);
                        }
                        bis2.close();
			boolean verifies = rsa.verify(realsign);
			System.out.println("signature verifies: " + verifies);

			System.out.println("Verification of signature completed at");
                        long end2=getCurrentTime();
                        System.out.println("Total elapsed time in ms= "+(end2-start2));

			/*********** Save signature in a file *************/
			FileOutputStream sigfos = new FileOutputStream(args[0]+".rsa_sign");
			sigfos.write(realsign);
			sigfos.close();

			/*********** Save Public key in a file *************/
			FileOutputStream pubkeyfos = new FileOutputStream(args[0]+".rsa_sign_public_key");
			pubkeyfos.write(publickey.getEncoded());
			pubkeyfos.close();

			/*********** Save Private key in a file *************/
			FileOutputStream prikeyfos = new FileOutputStream(args[0]+".rsa_sign_private_key");
			prikeyfos.write(privatekey.getEncoded());
			prikeyfos.close();

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