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


public class RSASignGen
{

  // for getting current time.
  public static long getCurrentTime()
  {
    java.util.Date date=Calendar.getInstance().getTime();
    Timestamp a=new Timestamp(date.getTime());
    long currentTime=Calendar.getInstance().getTimeInMillis();
    return currentTime;
  }
  
  public static void main(String args[])
  {

    if(args.length!=2){
      System.out.println("Usage: RSASignGen <name_of_file_to_sign> <message_size>");
      System.exit(0);
    }

    try{

      long begin,end;

      // for different key sizes.
      for(int keysize=512;keysize<=1024;keysize+=256)
      {

        System.out.println("Key Size : " + keysize);
        System.out.println("MessageSize\tSignGenerationTime\tVerification\tVerifiction Time");
        System.out.println("-----------------------------------------------------------------------------");

        int msgsize = Integer.valueOf(args[1]).intValue();

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

        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 private key **************/

        begin = 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[msgsize];

        int length;

        if(bis.available() != 0){
          length = bis.read(buffer);
          rsa.update(buffer,0,length);
          System.out.print(length + "\t\t");
        }

        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 = rsa.sign();

        end = getCurrentTime();

        System.out.print("\t" + (end-begin) + "\t\t");

        /*********** 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();

        /*********** Verify the Signature  *************/

        /*
        * For verifying the signature we need the data,
        * Signature, public key corresponding to the
        * private key with which we signed the data.
        */

        begin = getCurrentTime();
        
        rsa.initVerify(publickey);
        
        FileInputStream fis1 = new FileInputStream(args[0]);
        BufferedInputStream bis1 = new BufferedInputStream(fis1);

        byte buffer1[] = new byte[msgsize];

        if(bis1.available() != 0){
          length = bis1.read(buffer);
          rsa.update(buffer,0,length);
        }

        bis1.close();
        fis1.close();
        
        if(rsa.verify(realsign))
            System.out.print("Correct\t\t");
        else
            System.out.print("Not Correct\t\t");

        end = getCurrentTime();

        System.out.println((end-begin));

      }

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

  }
  
}
