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


public class DSASignGen
{

  // the function for knowing the 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: DSASignGen <name_of_file_to_sign> <message_size>");
      System.exit(0);
    }

    try{

      long begin,end;

      //for three 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(); //take the message size from the argument.
      
      
        /************************* BEGIN Generate a key pair ***************************/
        KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA");
        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 dsa = Signature.getInstance("SHA1withDSA");

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

        end = getCurrentTime();

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

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

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

        /*********** Save Private key in a file *************/
        FileOutputStream prikeyfos = new FileOutputStream(args[0]+".dsa_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();
        dsa.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(buffer1);
          dsa.update(buffer,0,length);
        }

        bis1.close();
        fis1.close();

        if(dsa.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();
    }
    
  }
}
