Página siguiente Página anterior Índice general

7.1 Arquitectura Criptográfica de Java (JCA)

La JCA es un marco de trabajo para acceder y desarrollar funciones criptográficas en la plataforma Java. Se diseñó alrededor de dos principios básicos:

  1. Idependencia e interoperabilidad de las implementaciones:
  2. Independencia y extensibilidad de los algoritmos:

La separación entre el JCA y el JCE está motivada por las reglas de exportación de los EEUU para la encriptación. Las clases distribuidas con el JDK estándar sólo proporcionan herramientas para el resumen de mensajes y las firmas digitales, lo que permite tener un sistema de autentificación fiable sobre el que implementar un sistema de control de acceso más flexible que el modelo del cajón de arena. El problema es que estas herramientas no son suficientes para el envío seguro de datos, que necesitan algoritmos de encriptación.

La solución a este último problema es el JCE, que emplea la misma estructura que el JCA y proporciona clases motor para implementar criptografía de clave simétrica y para la generación y manipulación de las claves que estos emplean.

Motor, algoritmo y proveedor

Antes de comenzar con la discusión del funcionamiento del JCA tenemos que definir algunos términos básicos:

Motor

En el contexto del JCA utilizamos el término motor (engine) para referirnos a una representación abstracta de un servicio criptográfico que no tiene una implementación concreta. Un servicio criptográfico siempre está asociado con un algoritmo o tipo de algoritmo y puede tener alguna de las siguientes funciones:

Algoritmo

Un algoritmo es una implementación de un motor. P. ej. el algoritmo MD5 es una implementación del motor de algoritmos de resumen de mensajes. La implementación interna puede variar dependiendo del código que proporcione la clase MD5.

Proveedor

Un proveedor es el encargado de proporcionar la implementación de uno o varios algoritmos al programador (es decir, darle acceso a una implementación interna concreta de los algoritmos).

El concepto de proveedor

La JCA define el concepto de proveedor mediante la clase Provider del paquete java.security. Se trata de una clase abstracta que debe ser redefinida por clases proveedor específicas.

El constructor de una clase proveedor ajusta los valores de varias propiedades que necesita el API de seguridad de Java para localizar los algoritmos u otras facilidades implementadas por el proveedor.

La clase Provider tiene métodos para acceder al nombre del proveedor, el número de versión y otras informaciones sobre las implementaciones de los algorirmos para la generación, conversión y gestión de claves y la generación de firmas y resumenes.

Para entender como funcionan los proveedores daremos un ejemplo. Supongamos que un programa necesita una implementación del algoritmo MD5. Para obtenerla el programador necesita crear una instancia del mismo y lo hará escribiendo la siguiente línea de código:

MessageDigest m = MessageDigest.getInstance("MD5");

Internamente, el método getInstance() solicita a la clase java.security.Security que le proporcione el objeto solicitado. Como no se ha especificado proveedor la clase Security consulta a todos los proveedores disponibles, solicitando una implementación del algoritmo "MD5", hasta que encuentra una o se queda sin proveedores. La consulta se realiza según la lista de proveedores del archivo java.security, que por defecto sólo contiene la entrada:

Security.provider.1=sun.security.provider.Sun

Si se encuentra una implementación se retorna una instancia de la clase retornada por el proveedor y si no se genera la excepción NoSuchAlgorithmException. En caso de que se haya obtenido una implementación, para generar el resumen de un vector de bytes (p. ej. buf) con el MD5 bastará invocar el método update() del algoritmo. Para obtener el vector resumen invocaremos el método digest():

m.update(buf);
byte[] resumen = m.digest();

Por último sólo nos queda saber como se gestionan los proveedores, es decir, como se instalan o eliminan.

Existen dos modos de hacerlo:

  1. Estáticamente, editando las entradas del fichero java.security
  2. Dinámicamente, invocando desde el programa los métodos addProvider() o insertProvider() de la clase java.security.Security para añadirlos o al método removeProvider()

Si un programador desea saber los proveedores disponibles puede emplear los métodos getProvider("nombre") (para saber si un proveedor concreto está instalado) o getProviders() (que retorna un vector de cadenas con los nombres de los proveedores).

Las clases Motor

En el JDK 1.2 el JCA define las clases motor presentadas en la tabla Clases motor de la JCA 1.2 y el JCE las de la tabla Clases motor de la JCE 1.2.


Clase JCA 1.2
Función
java.security.MessageDigestCalculo de resumen de mensajes (hash).
java.security.SignatureFirmado de datos y verificación firmas.
java.security.KeyPairGeneratorGenerar pares de claves (pública y privada) para un algoritmo.
java.security.KeyFactoryConvertir claves de formato criptográfico aespecificaciones de claves y vice versa
java.security.certificate.CertificateFactoryCrear certificados de clave pública y listas de revocación(CRLs).
java.security.KeyStoreCrear y gestionar un almacen de claves (keystore).
java.security.AlgorithmParametersGestionar los parámetros de un algoritmo, incluyendocodificación y descodificación.
java.security.AlgorithmParameterGeneratorGenerar un conjunto de parámetros para un algoritmo.
java.security.SecureRandomGenerar números aleatrorios o pseudo aleatrorios.
Clases motor de la JCA 1.2


Clase JCE 1.2
Función
java.crypto.CipherProporciona encriptación y desencriptación.
java.crypto.KeyAgreementProporciona un protocolo de intercambio de claves.
java.crypto.KeyGeneratorProporciona un generador de claves simétricas.
java.crypto.MacProporciona un algoritmo de autentificación de mensajes.
java.crypto.SecretKeyFactoryRepresenta una factoría de claves secretas.
Clases motor de la JCE 1.2

Para instanciar una clase motor se debe invocar el método estático getInstance(), si se le pasa un nombre de algoritmo se intentará obtener una implementación de algún proveedor (ver ejemplo en

Algoritmos

El siguiente programa nos permite saber que proveedores y algoritmos tenemos instalados en nuestro sistema. Además, si lo invocamos con la opción -l nos dirá que algoritmos implementan (leyendo las propiedades del proveedor):



// InfoProveedores.java
import java.security.*;
import java.util.*;

class InfoProveedores {
  public static void main(String[] args) {
    boolean listarProps = false;
    if ( args.length > 0 && args[0].equals("-l") )
      listarProps=true;
    System.out.println("------------------------------------");
    System.out.println("Proveedores instalados en su sistema");
    System.out.println("------------------------------------");
    Provider[] listaProv = Security.getProviders();
    for (int i = 0; i < listaProv.length; i++) {
      System.out.println("Núm. proveedor : "    + (i + 1));
      System.out.println("Nombre         : "    + listaProv[i].getName());
      System.out.println("Versión        : "    + listaProv[i].getVersion());
      System.out.println("Información    :\n  " + listaProv[i].getInfo());
      System.out.println("Propiedades    :");
      if (listarProps) {
        Enumeration propiedades = listaProv[i].propertyNames();
        while (propiedades.hasMoreElements()) {
          String clave = (String) propiedades.nextElement();
          String valor = listaProv[i].getProperty(clave);
          System.out.println("  " + clave + " = " + valor);
        }
      }
      System.out.println("------------------------------------");
    }
  }
}

Por defecto el JDK 1.2 incluye el proveedor de JCA SUN, para saber que algoritmos implementa ejecutar el programa con la opción -f.


Página siguiente Página anterior Índice general