Security en JDK 1.2

CC60H
Bárbara Poblete

Para conocer un breve historia de la evolución de Security en Java revise el overview del tutorial de JDK 1.2

Generar y Verificar Firmas

El paquete de Security en JDK 1.2 tiene muchas funcionalidades diferentes y en esta presentación solo nos referiremos a un aspectos, que es firmar digitalmente archivos y verificar esta firma. Esto será ilustrado con dos ejemplos.

Generar una firma digital

Mostraremos usando la API como generar llaves, una firma digital para datos usando la llave privada, y a exportar la llave pública y la firma a archivos.

Estructura del Programa

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


class GenSig {

    public static void main(String[] args) {

        /* Generamos la firma DSA */


        if (args.length != 1) {
            System.out.println("Usage: GenSig nameOfFileToSign");
            }
        else try {

        // El resto del código va aquí

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }
}

Generación de Llaves

Creación de un generador de pares de llaves

Agregamos en el código anterior después de:

	else try {
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");

Inicialización del generador de pares de llaves

	SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
	keyGen.initialize(1024, random);


Generación de las llaves

	KeyPair pair = keyGen.generateKeyPair();
	PrivateKey priv = pair.getPrivate();
	PublicKey pub = pair.getPublic();


Firmamos los datos

Ahora que tenemos las llaves públicas y privadas podemos firmar la información. Una firma digital puede ser verificada o creada usando una instancia de la clase Signature.

Obtención de un objeto de tipo Signature

	Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

Inicialización del objeto Signature

	dsa.initSign(priv);

Entrega al objeto Signature de los datos a ser firmados

	FileInputStream fis = new FileInputStream(args[0]);
	BufferedInputStream bufin = new BufferedInputStream(fis);
	byte[] buffer = new byte[1024];
	int len;
		while (bufin.available() != 0) {
    			len = bufin.read(buffer);
    			dsa.update(buffer, 0, len);
		};
	bufin.close();

Generación de la firma

	byte[] realSig = dsa.sign();

Almacenamos la firma

	/* guardamos la firma en un archivo */ 
	FileOutputStream sigfos = new FileOutputStream("sig");
	sigfos.write(realSig);
	sigfos.close();

Almacenamos la llave

	/* guardamos la llave publica en un archivo */ 
	byte[] key = pub.getEncoded(); 
	FileOutputStream keyfos = new FileOutputStream("pk");
	keyfos.write(key); 
	keyfos.close();

Probar el programa

El código completo del programa esta disponible, GenSig.java y se una vez compilado se ejecuta de la siguiente manera:

	%java GenSig data

Este programa sólo lee el archivo data, no lo modifica y genera un archivo sig que contiene la firma digital acorde la llave privada pk y a los datos.

Verificar una firma digital

Para poder verificar una firma digital incluida junto a algun archivo de datos necesitamos:

Estructura del Programa

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


class VerSig {

    public static void main(String[] args) {

        /* Verificamos la firma DSA */
        if (args.length != 3) {
            System.out.println("Usage: VerSig publickeyfile signaturefile datafile");
            }
        else try {

        // El resto del código va aquí

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }
}

Ingreso y conversión de los bytes encodeados de la llave pública

	FileInputStream keyfis = new FileInputStream(args[0]);
	
	byte[] encKey = new byte[keyfis.available()];  
	keyfis.read(encKey);
	keyfis.close();

Especificación de la llave, asumiendo que fue encodeada de acuerdo a el estándar X.509

	X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);


Hacemos la conversión

	KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");

Ahora podemos generar la llave pública de la especificación

	PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

Ahora ingresamos los bytes de la firma

	FileInputStream sigfis = new FileInputStream(args[1]);
	
	byte[] sigToVerify = new byte[sigfis.available()];
	sigfis.read(sigToVerify);
	sigfis.close();

Inicializamos el objeto Signature para la verificación

	Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
	sig.initVerify(pubKey);

Entregar los datos al objeto Signature para que sean verificados

	FileInputStream datafis = new FileInputStream(args[2]);
	BufferedInputStream bufin = new BufferedInputStream(datafis);

	byte[] buffer = new byte[1024];
	int len;
	
	while (bufin.available() != 0) {
   		len = bufin.read(buffer);
		sig.update(buffer, 0, len);
	};

Verificar la firma

	boolean verifies = sig.verify(sigToVerify);
	System.out.println("signature verifies: " + verifies);

Probar el programa

El código completo del programa esta disponible, VerSig.java y se una vez compilado se ejecuta de la siguiente manera:

	%java VerSig pk sig data
	signature verifies: true