public final class AOXAdESSigner extends java.lang.Object implements AOSigner
Soporta XAdES-BES y XAdES-EPES.
Debido a errores en algunas versiones del entorno de ejecución de Java, esta clase puede generar ocasionalmente
mensajes en consola del tipo: [Fatal Error] :1:1: Content is not allowed in prolog.
. Estos
deben ignorarse, ya que no indican ninguna condición de error ni malfuncionamiento.
Los atributos específicos XAdES implementados por esta clase (además de los relativos a las politicas de firma) son:
Distintos formatos de firmas XML
La firma XML en modo Detached permite tener una firma de forma separada e independiente del
contenido firmado, pudiendo relacionar firma con contenido firmado mediante una referencia de tipo
URI. Este tipo de firmas es útil cuando no se puede modificar el contenido original pero se
desea constatar su autenticidad, procedencia, etc.
Un uso común de este formato es en la descarga de ficheros, pudiendo poner a disposición del internauta, junto al contenido a descargar, un pequeño fichero de firma para verificar la integridad del primero.
Un ejemplo de este tipo de firmas sería la siguiente estructura (resumida) XML:
<?xml version="1.0" encoding="UTF-8"?> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="http://www.mpt.es/contenido"> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue/> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue/> </ds:Signature>
En este ejemplo, los datos firmados se encuentran en un servidor Web accesible públicamente: http://www.mpt.es/contenido, y se referencia como tal, conformando lo que se denomina Externally Detached o "Detached Externa".
Cuando se desea firmar un contenido con un formato Detached, pero se quiere eliminar la dependencia de la disponibilidad externa del contenido firmado, es posible crear una estructura XML que contenga los propios contenidos y la firma, pero cada uno en una subestructura independiente, manteniendo asi el concepto de Detached (firma y contenido firmado no se interrelacionan directamente). Para adecuarse al estándar los nodos de firma y contenido debe encontrarse en el mismo nivel dentro del XML.
Un ejemplo de esta estructura XML sería:
<?xml version="1.0" encoding="UTF-8"?> <internally-detached> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#data"> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue/> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue/> </ds:Signature> <document Id="data"> <title>title</title> <author>writer</author> <date>today</date> <content> <para>First paragraph</para> <para>Second paragraph</para> </content> </document> </internally-detached>
En este caso, la estructura internally-detached contiene dos subestructuras, la firma (Signature) y el propio contenido firmado (document). La forma de relacionar ambos es, como ocurría en el primer ejemplo, con una URI, solo que en este caso es interna al documento XML, referenciando el identificador de la subestructura del contenido firmado (data).
A esta variante de firma Detached se la conoce como Internally Detached, o "Detached Interna".
Para unificar las superestructuras creadas dentro de un formato "Detached Interno", el Cliente @firma construye siempre el siguiente esqueleto XML:
<CONTENT Id="id" Encoding="codificacion" MimeType="MimeType" Algorithm=""> <! CONTENIDO FIRMADO --> </CONTENT>
Es decir, el contenido a firmar, ya sea XML o no-XML, se encapsula dentro de una etiqueta XML llamada CONTENT, en la que se indica la codificación del contenido (UTF-8, Base64, etc.), el tipo de contenido (imagen JPEG, texto, XML, etc.) y el algoritmo utilizado para calcular la huella digital de este (por ejemplo, SHA-1).
Como la superestructura es XML, si el contenido también es XML la inserción es directa (como en el primer ejemplo de "Detached Interna", pero si no es XML se codifica en Base64 antes de insertarse, resultando una estructura con una forma similar a la siguiente:
<CONTENT Id="id" Encoding="Base64" MimeType="application/octect-stream" Algorithm=""> SFGJKASGFJKASEGUYFGEYGEYRGADFJKASGDFSUYFGAUYEGWEYJGDFYKGYKGWJKEGYFWYJ= </CONTENT>
La larga cadena de caracteres sería una codificación Base64 del original interpretado en su forma binaria pura.
Otra variante de firma es la Enveloping, en la que la estructura XML de firma es la única en el documento de firma, y esta contiene internamente el contenido firmado (en un nodo propio).
<?xml version="1.0" encoding="UTF-8"?> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#obj"> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue/> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue/> <ds:Object Id="obj">SFGJKASGFJKASEGUYFGEYGEYRGADFJKASGDFSUYFG=</ds:Object> </ds:Signature>
En este caso, los datos firmados se encuentran en el nodo Object, referenciados internamente al XML mediante el identificador obj.
Al igual que ocurría con el formato Detached, si los datos no son XML, no es posible insertarlos directamente dentro de una estructura XML, por lo que se codifican previamente en Base64.
Este formato de firma XMLDSig está pensado para que un contenido XML pueda auto-contener su propia firma digital, insertándola en un nodo propio interno, por lo que, al contrario que en los formatos anteriores, no es posible firmar contenido que no sea XML.
Un ejemplo simple del resultado de una firma Enveloped podría ser el siguiente:
<!DOCTYPE Enveloped [ <!ENTITY ds "http://www.w3.org/2000/09/xmldsig#"> <!ENTITY c14n "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"> <!ENTITY enveloped "http://www.w3.org/2000/09/xmldsig#enveloped-signature"> <!ENTITY xslt "http://www.w3.org/TR/1999/REC-xslt-19991116"> <!ENTITY digest "http://www.w3.org/2000/09/xmldsig#sha1"> ]> <Letter> <Return-address>address</Return-address> <To>You</To> <Message>msg body</Message> <From> <ds:Signature xmlns:ds="ds"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI=""> <ds:Transforms> <ds:Transform Algorithm="enveloped"></ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="digest"/> <ds:DigestValue></ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue/> </ds:Signature> </From> <Attach>attachement</Attach> </Letter>
En este caso, el documento original (Letter), contiene internamente la estructura de firma digital (Signature).
Una peculiaridad de la estructura generada es que esta referenciada mediante una URI vacía
(URI=""
), lo cual indica que la firma aplica a la totalidad del documento original.
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
SIGNATURE_TAG
Etiqueta de los nodos firma de los XML firmados.
|
Constructor and Description |
---|
AOXAdESSigner() |
Modifier and Type | Method and Description |
---|---|
byte[] |
cosign(byte[] data,
byte[] sign,
java.lang.String algorithm,
java.security.PrivateKey key,
java.security.cert.Certificate[] certChain,
java.util.Properties xParams)
Cofirma datos en formato XAdES.
|
byte[] |
cosign(byte[] sign,
java.lang.String algorithm,
java.security.PrivateKey key,
java.security.cert.Certificate[] certChain,
java.util.Properties extraParams)
Cofirma datos en formato XAdES.
|
byte[] |
countersign(byte[] sign,
java.lang.String algorithm,
CounterSignTarget targetType,
java.lang.Object[] targets,
java.security.PrivateKey key,
java.security.cert.Certificate[] certChain,
java.util.Properties xParams)
Contrafirma firmas en formato XAdES.
|
byte[] |
getData(byte[] sign)
Recupera los datos originalmente firmados de una firma.
|
java.lang.String |
getSignedName(java.lang.String originalName,
java.lang.String inText)
Devuelve el nombre de fichero de firma recomendado para el resultado de firmar un fichero
con el nombre proporcionado.
|
AOTreeModel |
getSignersStructure(byte[] sign,
boolean asSimpleSignInfo)
Recupera el árbol de nodos de firma de una firma electrónica.
|
AOSignInfo |
getSignInfo(byte[] sign)
Obtiene la información general de un objeto de firma.
|
static boolean |
isDetached(org.w3c.dom.Element element)
Comprueba si la firma es detached.
|
static boolean |
isEnveloped(org.w3c.dom.Element element)
Comprueba si la firma es enveloped.
|
static boolean |
isEnveloping(org.w3c.dom.Element element)
Comprueba si la firma es enveloping.
|
boolean |
isSign(byte[] sign)
Indica si un dato es una firma compatible con la implementación concreta.
|
boolean |
isValidDataFile(byte[] data)
Comprueba si el dato introducido es válido para ser firmado por
este manejador de firma.
|
byte[] |
sign(byte[] data,
java.lang.String algorithm,
java.security.PrivateKey key,
java.security.cert.Certificate[] certChain,
java.util.Properties xParams)
Firma datos en formato XAdES.
|
public static final java.lang.String SIGNATURE_TAG
public byte[] sign(byte[] data, java.lang.String algorithm, java.security.PrivateKey key, java.security.cert.Certificate[] certChain, java.util.Properties xParams) throws AOException
Este método, al firmar un XML, firmas también sus hojas de estilo XSL asociadas, siguiendo el siguiente criterio:
sign
in interface AOSimpleSigner
data
- Datos que deseamos firmar.algorithm
- Algoritmo a usar para la firma.
Se aceptan los siguientes algoritmos en el parámetro algorithm
:
key
- Clave privada a usar para firmar.certChain
- Cadena de certificados del clientexParams
- Parámetros adicionales para la firma (detalle)AOException
- Cuando ocurre cualquier problema durante el procesopublic static boolean isDetached(org.w3c.dom.Element element)
element
- Elemento que contiene el nodo raíz del documento que se
quiere comprobarpublic static boolean isEnveloped(org.w3c.dom.Element element)
element
- Elemento que contiene el nodo raíz del documento que se
quiere comprobarpublic static boolean isEnveloping(org.w3c.dom.Element element)
element
- Elemento que contiene el nodo raíz del documento que se
quiere comprobarpublic byte[] getData(byte[] sign) throws AOInvalidFormatException
null
.getData
in interface AOSigner
sign
- Datos de firma o fichero firmado.AOInvalidFormatException
- Si no se ha introducido un fichero de firma válido o no
ha podido leerse la firma.public byte[] cosign(byte[] data, byte[] sign, java.lang.String algorithm, java.security.PrivateKey key, java.security.cert.Certificate[] certChain, java.util.Properties xParams) throws AOException
Este método firma todas las referencias a datos declaradas en la firma original, ya apunten estas a datos, hojas de estilo o cualquier otro elemento. En cada referencia firmada se introduciran las mismas transformaciones que existiesen en la firma original.
A nivel de formato interno, cuando cofirmamos un documento ya firmado previamente, esta
firma previa no se modifica. Si tenemos en cuenta que XAdES es en realidad un subconjunto
de XMLDSig, el resultado de una cofirma XAdES sobre un documento firmado previamente con
XMLDSig (o viceversa), son dos firmas independientes, una en XAdES y otra en XMLDSig.
Dado que todas las firmas XAdES son XMLDSig pero no todas las firmas XMLDSig son XAdES,
el resultado global de la firma se adecúa al estandar mas amplio, XMLDSig en este caso.
cosign
in interface AOCoSigner
data
- No se utiliza.sign
- Documento con las firmas iniciales.algorithm
- Algoritmo a usar para la firma.
Se aceptan los siguientes algoritmos en el parámetro algorithm
:
key
- Clave privada a usar para firmar.certChain
- Cadena de certificados del cliente.xParams
- Parámetros adicionales para la firma (detalle)AOException
- Cuando ocurre cualquier problema durante el procesopublic byte[] cosign(byte[] sign, java.lang.String algorithm, java.security.PrivateKey key, java.security.cert.Certificate[] certChain, java.util.Properties extraParams) throws AOException
Este método firma todas las referencias a datos declaradas en la firma original, ya apunten estas a datos, hojas de estilo o cualquier otro elemento. En cada referencia firmada se introduciran las mismas transformaciones que existiesen en la firma original.
A nivel de formato interno, cuando cofirmamos un documento ya firmado previamente, esta
firma previa no se modifica. Si tenemos en cuenta que XAdES es en realidad un subconjunto
de XMLDSig, el resultado de una cofirma XAdES sobre un documento firmado previamente con
XMLDSig (o viceversa), son dos firmas independientes, una en XAdES y otra en XMLDSig.
Dado que todas las firmas XAdES son XMLDSig pero no todas las firmas XMLDSig son XAdES,
el resultado global de la firma se adecúa al estandar mas amplio, XMLDSig en este caso.
cosign
in interface AOCoSigner
sign
- Documento con las firmas iniciales.algorithm
- Algoritmo a usar para la firma.
Se aceptan los siguientes algoritmos en el parámetro algorithm
:
key
- Clave privada a usar para firmar.certChain
- Cadena de certificados del firmante.extraParams
- Parámetros adicionales para la firma (detalle)AOException
- Cuando ocurre cualquier problema durante el procesopublic byte[] countersign(byte[] sign, java.lang.String algorithm, CounterSignTarget targetType, java.lang.Object[] targets, java.security.PrivateKey key, java.security.cert.Certificate[] certChain, java.util.Properties xParams) throws AOException
Este método contrafirma los nodos de firma indicados de un documento de firma.
countersign
in interface AOCounterSigner
sign
- Documento con las firmas iniciales.algorithm
- Algoritmo a usar para la firma.
Se aceptan los siguientes algoritmos en el parámetro algorithm
:
targetType
- Mecanismo de selección de los nodos de firma que se deben
contrafirmar.
Las distintas opciones son:
target
target
Cada uno de estos tipos se define en CounterSignTarget
.
targets
- Listado de nodos o firmantes que se deben contrafirmar según el
targetType
seleccionado.key
- Clave privada a usar para firmar.certChain
- Cadena de certificados del firmante.xParams
- Parámetros adicionales para la firma (detalle)AOException
- Cuando ocurre cualquier problema durante el procesopublic AOTreeModel getSignersStructure(byte[] sign, boolean asSimpleSignInfo) throws AOInvalidFormatException
AOSimpleSignInfo
con la
información básica de las firmas individuales, según
el valor del parámetro asSimpleSignInfo
. Los nodos se
mostrarán en el mismo orden y con la misma estructura con el que
aparecen en la firma electrónica.getSignersStructure
in interface AOSigner
sign
- Firma electrónica de la que se desea obtener la estructura.asSimpleSignInfo
- Si es true
se devuelve un árbol con la
información básica de cada firma individual
mediante objetos AOSimpleSignInfo
, si es false
un árbol con los nombres (CN X.500) de los
titulares de los certificados.null
en caso de error.AOInvalidFormatException
- Si no se ha introducido un fichero de firma válido del formato correspondiente.public boolean isSign(byte[] sign)
public boolean isValidDataFile(byte[] data)
isValidDataFile
in interface AOSigner
data
- Dato que deseamos comprobar.true
si el dato es susceptible de ser firmado por la implementación concreta,
false
en caso contrario.public java.lang.String getSignedName(java.lang.String originalName, java.lang.String inText)
getSignedName
in interface AOSigner
originalName
- Nombre del fichero original que se firmainText
- Partícula intermedia que agregar al nombre del fichero de
firma.public AOSignInfo getSignInfo(byte[] sign) throws AOException
getSignInfo
in interface AOSigner
sign
- Firma que se desea analizar.AOInvalidFormatException
- Cuando la firma introducida no es un objeto de firma
reconocido por este manejador.AOException
- Ocurrió un error durante la recuperación de los
datos.