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

/**
 * <p>Example 2 exercises the PKCS8EncodedKeySpec, X509EncodedKeySpec
 *    and KeyFactory classes.
 *    
 *    As in Example 1, an RSA key pair is generated. The keys are then
 *    saved to disk. The saved keys are then loaded from disk and used 
 *    to sign a message and verify the signature.
 */
public class Example2
{
  public static void main(String args[])
  {
    try
    {
      System.out.println("Seeding random number generator ...");
      SecureRandom rand = new SecureRandom();
      rand.nextInt();
  
      // We want RSA keys of key length = 1024 bits
      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
      kpg.initialize(1024, rand);
  
      System.out.println("Generating keys ...");
      KeyPair kp = kpg.generateKeyPair();
      PrivateKey priv = kp.getPrivate();
      PublicKey pub = kp.getPublic();

      // Save keys to disk
      InputStreamReader isr = new InputStreamReader(System.in);
      BufferedReader in = new BufferedReader(isr);
      FileOutputStream outFile;
      FileInputStream inFile;

      // Save private key
      System.out.print("\nEnter filename to save private key: ");
      outFile = new FileOutputStream(in.readLine());
      outFile.write(priv.getEncoded());
      System.out.println("Key saved");

      // Save public key
      System.out.print("\nEnter filename to save public key: ");
      outFile = new FileOutputStream(in.readLine());
      outFile.write(pub.getEncoded());
      System.out.println("Key saved");

      // We want to use MD5withRSA
      Signature signature = Signature.getInstance("MD5withRSA");
  
      // Read in encoded private key
      System.out.print("\nEnter filename to load private key: ");
      inFile = new FileInputStream(in.readLine());
      byte[] keyBytes = new byte[inFile.available()];
      inFile.read(keyBytes);
      PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyBytes);

      // Turn encoded key bytes into PrivateKey
      KeyFactory keyFact = KeyFactory.getInstance("RSA");
      priv = keyFact.generatePrivate(privKeySpec);

      // Initialize for signing
      signature.initSign(priv);
      
      // Data to be signed  
      byte[] data = "Hello, world!".getBytes();
  
      // Sign it and returns signature bytes
      signature.update(data);
      byte[] sigBytes = signature.sign();
  
      // Read in encoded public key
      System.out.print("\nEnter filename to load public key: ");
      inFile = new FileInputStream(in.readLine());
      keyBytes = new byte[inFile.available()];
      inFile.read(keyBytes);
      X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyBytes);

      // Turn encoded key bytes into PublicKey
      pub = keyFact.generatePublic(pubKeySpec);

      // Initialize for verification
      signature.initVerify(pub);
  
      // Verify signature
      signature.update(data);
      boolean isVerified = signature.verify(sigBytes);
  
      System.out.println("Signature verifies: " + isVerified);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}  
