Certificados digitales

Las clases para el tratamiento de certificados se encuentran en es.accv.arangi.base.certificate y es.accv.arangi.certificate. La mayor parte de la siguiente explicación sólo es útil para trabajar con certificados de la ACCV y el DNIe con la librería Arangí, si desea trabajar con otros prestadores de certificación lea el apartado 'Otros prestadores (CAs)' y utilice la librería Arangí Base.

Este es el esquema de clases para certificados digitales de la Agencia de Tecnología y Certificación Electrónica:

  Certificate
  |
  |  ValidateCertificate
  |  |
  |  |  CertificadoPersona
  |  |  |
  |  |  |  CertificadoCiudadano
  |  |  |  CertificadoEmpleadoPublico
  |  |  |  CertificadoPertenenciaEmpresa
  |  |  |  CertificadoRepresentante
  |  |  |  CertificadoDNIe
  |  |
  |  |  CertificadoEntidad
  |  |  CertificadoAplicacion
  |  |  CertificadoSede
  |  |  CertificadoSello
  |  |  CertificadoSeudonimo
  |  |  CertificadoDesconocido

Todas las clases derivan de Certificate y ValidateCertificate, clases de la librería base de Arangí. La clase Certificate ofrece los métodos necesarios para obtener todo tipo de información sobre un certificado digital. La clase ValidateCertificate es una extensión de Certificate que se inicia con un objeto CAList que contiene todos los certificados de Autoridades de Certificación sobre los que se desea trabajar. De esta forma ValidateCertificate es capaz de obtener la cadena de certificación del certificado y por tanto puede realizar una validación completa del mismo. El resto de clases, que se encuentran en la librería de Arangí, al extender de ValidateCertificate poseen también la capacidad de realizar la validación de sus certificados.

La clase CertificadoPersona es abstracta y ofrece metodos para aquellos certificados asignados a personas: obtención de DNI, nombre, apellidos y e-mail.

Obtención de la clase adecuada para el certificado

En ciertas ocasiones se debe obtener información muy concreta de certificados que llegan al sistema y pueden ser de cualquier tipo. Por ejemplo, el NIF en certificados personales o el nombre de la aplicación en un certificado de aplicación. En esas circunstancias se hace necesario poder discriminar por tipo de certificado y, en última instancia, tratar con la información contenida en dicho certificado. En el siguiente ejemplo se muestra como se aceptarían sólo certificados personales y se obtendría el nombre y los apellidos del propietario del certificado dentro de una comunicación SSL con identificación de cliente:

X509Certificate[] certs = (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
if (certs != null && certs.length > 0) { 
        X509Certificate clientCert = certs[0];
        if (clientCert != null) {
                
                ValidateCertificate validateCertificate = CertificateFactory.getInstance(new Certificate(clientCert));
                if (validateCertificate == null || !(validateCertificate instanceof CertificadoPersona)) {
                        throw new Exception ("El certificado no es admitido");
                }
                
                CertificadoPersona certificadoPersona = (CertificadoPersona) validateCertificate;
                String nombre = certificadoPersona.getName();
                String apellidos = certificadoPersona.getSurnames();
                
        }
}

Como puede observarse, el método getInstance de CertificateFactory devuelve un objeto de la clase adecuada para tratar el certificado. En caso de que el certificado no pertenezca a los tratados por Arangí el método devolverá null.

Una vez se ha comprobado el tipo del certificado sólo es necesario realizar un cast para obtener el objeto adecuado para tratar la información del certificado.

Obtención de los campos de un certificado

En el punto anterior se ha podido ver cómo obtener los campos específicos de cada tipo de certificado. Si se desea utilizar certificados que no pertenecen a los emitidos por la ACCV o el DNIe sólo hay dos posibilidades a la hora de obtener sus campos:

  • Ampliar arangi_base para añadir clases que traten este tipo de certificados.
  • Utilizar algún tipo de servicio externo al que proporcionar el certificado y que nos devuelva sus campos.

La primera opción es útil si se van a tratar unos pocos tipos de certificado, pero se convierte en algo inmanejable si se desea, por ejemplo, tratar con todos los certificados emitidos por las autoridades de certificación de un país.

En España existe el servicio web de @Firma que permite obtener los campos de todos los certificados emitidos por las autoridades de certificación reconocidas. Si se quiere hacer uso de este servicio desde Arangí el código sería como sigue:

Certificate certificado = ...

CertificateDataService servicio1 = new AFirmaCertificateDataService(AFirmaCertificateDataService.TEST_URL, "ACCVTEST.MIAPLICACION", null, null, null);
List<CertificateDataService> lServicios = new ArrayList<CertificateDataService>();
lServicios.add(servicio1);

Map<String,String> result  = certificado.getData(dataServices);

También se puede utilizar @Firma 6 y sus servicios DSS. Es una mejor opción ya que éstos tienen un mayor recorrido y permiten la securización mediante firma digital (WSS4J). El problema de esta opción es que sólo se devuelven los campos para certificados válidos.

CertificateDataService servicio1 = new AFirma6CertificateDataService("afirma6.accv.es:8444", "ACCVTEST.MIAPLICACION", null, null, null);

Puede ver cómo configurar la seguridad para acceder a este servicio aquí.