import java.security.Signature;
import java.security.SignatureException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

import sun.misc.*;

// Ejemplo de uso de firmas digitales: 
// (1) Se crea un par RSA y se firma el texto con la clave privada.
// (2) Se muestra la firma obtenida en BASE64
// (3) Verifica la firma con la correspondiente clave pública
public class FirmaDigital {

  public static void main (String[] args) throws Exception {

	if (args.length != 1) {
	  System.err.println("Uso: java FirmaDigital \"texto a firmar\"");
	  System.exit(1);
	}

    System.out.println("Generando un par RSA...");
    KeyPairGenerator generador = KeyPairGenerator.getInstance("RSA");
    generador.initialize(1024);
    KeyPair parClaves = generador.genKeyPair();
    System.out.println("Generando el par de claves.");

    // Tomar los bytes de datos a firmar del primer argumento
    byte[] datos = args[0].getBytes("UTF8");

    // Obtener instancia del objeto Signature e inicializarlo con 
    // la clave privada para firmarlo
    Signature firma = Signature.getInstance("MD5WithRSA");
    firma.initSign(parClaves.getPrivate());

    // Prepara la firma de los datos
    firma.update(datos);

    // Firmar los datos
    byte[] bytesFirma = firma.sign();

    // Mostrar en ASCII
    System.out.println("\nFirma:\n" + 
         new BASE64Encoder().encode(bytesFirma));

    // Ahora procedemos a verificar la firma. Para ello necesitaremos 
    // reinicializar el objeto Signature con la clave pública. 
    // Esto hace un reset de los datos de la firma con lo que hay que 
    // pasárselos de nuevo para hacer el update.
    firma.initVerify(parClaves.getPublic());

    // Pasar los datos que fueron firmados
    firma.update(datos);

    // Verificar
    boolean verificado = false;
    try {
      verificado = firma.verify(bytesFirma);
    } catch (SignatureException se) {
	  verificado = false;
    }

    if (verificado) {
      System.out.println("\nFirma verificada.");
    } else {
      System.out.println("\nFirma incorrecta.");
    }
  }
}

