Ejemplo de firma XAdES EPES - gdiazs/MITyCLib GitHub Wiki
El objetivo de este ejemplo es mostrar los pasos necesarios para realizar una firma XAdES-EPES. En cuanto al tipo de firma, se elige firma Enveloped, por lo que es imprescindible entender el ejemplo de firma Enveloped previamente ya que los conceptos son los mismos.
Siendo el documento original a firmar el siguiente:
<?xml version="1.0" encoding="UTF-8"?>
<documento id="documento">
<titulo id="titulo">Documento de pruebas</titulo>
<descripcion id="descripcion">Documento destinado a realizar pruebas de firma</descripcion>
</documento>
Una firma XAdES-EPES Enveloped en la que se firma todo el documento completo tendría el siguiente aspecto:
<?xml version="1.0" encoding="UTF-8"?>
<documento id="documento">
<titulo id="titulo">Documento de pruebas</titulo>
<descripcion id="descripcion">Documento destinado a realizar pruebas de firma</descripcion>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" Id="Signature504735">
<ds:SignedInfo Id="Signature-SignedInfo1024952">
<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 Id="SignedPropertiesID429729" Type="http://uri.etsi.org/01903#SignedProperties" URI="#Signature504735-SignedProperties48056">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue><!-- Digest del elemento referenciado en Base64 --></ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#Certificate1237555">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue><!-- Digest del elemento referenciado en Base64 --></ds:DigestValue>
</ds:Reference>
<ds:Reference Id="Reference-ID-200615" URI="">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue><!-- Digest del elemento referenciado en Base64 --></ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="SignatureValue552465">
<!-- Valor de la firma en Base64 -->
</ds:SignatureValue>
<ds:KeyInfo Id="Certificate1237555">
<ds:X509Data>
<ds:X509Certificate>
<!-- Certificado firmante en Base64 -->
</ds:X509Certificate>
</ds:X509Data>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus><!-- Módulo de la clave RSA en Base64 --></ds:Modulus>
<ds:Exponent><!-- Exponente de la clave RSA en Base64 --></ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
<ds:Object Id="Signature504735-Object873466">
<etsi:QualifyingProperties Target="#Signature504735">
<etsi:SignedProperties Id="Signature504735-SignedProperties48056">
<etsi:SignedSignatureProperties>
<etsi:SigningTime><!-- Fecha y hora de la firma --></etsi:SigningTime>
<etsi:SigningCertificate>
<etsi:Cert>
<etsi:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue><!-- Digest del certificado en Base64 --></ds:DigestValue>
</etsi:CertDigest>
<etsi:IssuerSerial>
<ds:X509IssuerName><!-- Nombre de emisión del certificado firmante --></ds:X509IssuerName>
<ds:X509SerialNumber><!-- Número de serie del certificado firmante --></ds:X509SerialNumber>
</etsi:IssuerSerial>
</etsi:Cert>
</etsi:SigningCertificate>
<etsi:SignaturePolicyIdentifier>
<etsi:SignaturePolicyImplied/>
</etsi:SignaturePolicyIdentifier>
</etsi:SignedSignatureProperties>
<etsi:SignedDataObjectProperties>
<etsi:DataObjectFormat ObjectReference="#Reference-ID-200615">
<etsi:Description><!-- Descripcion del objeto firmado ---></etsi:Description>
<etsi:MimeType><!-- Tipo MIME del objeto firmado --></etsi:MimeType>
</etsi:DataObjectFormat>
</etsi:SignedDataObjectProperties>
</etsi:SignedProperties>
</etsi:QualifyingProperties>
</ds:Object>
</ds:Signature>
</documento>
Si se compara esta firma con la firma XAdES-BES se puede observar que lo que aporta sobre ella es información explícita de la política a utilizar (tag etsi:SignaturePolicyIdentifier).
El programa de ejemplo extiende el ejemplo de firma genérica implementando aquellos métodos abstractos que lo hacen específico para el formato de firma XAdES-EPES. El código completo del ejemplo se puede ver aquí. También se puede ver el Javadoc asociado al ejemplo aquí.
La implementación del método abstracto createDataToSign() de la clase GenericXMLSignature es la siguiente:
@Override
protected DataToSign createDataToSign() {
DataToSign dataToSign = new DataToSign();
dataToSign.setXadesFormat(EnumFormatoFirma.XAdES_BES);
dataToSign.setEsquema(XAdESSchemas.XAdES_132);
dataToSign.setPolicyKey(POLICY_TO_APPLY);
dataToSign.setAddPolicy(true);
dataToSign.setXMLEncoding("UTF-8");
dataToSign.addClaimedRol(new SimpleClaimedRole("Rol de firma"));
dataToSign.setEnveloped(true);
dataToSign.addObject(new ObjectToSign(new AllXMLToSign(), "Documento de ejemplo", null, "text/xml", null));
Document docToSign = getDocument(RESOURCE_TO_SIGN);
dataToSign.setDocument(docToSign);
return dataToSign;
}
Como se puede ver, el código es similar al mostrado en el ejemplo de firma Enveloped. La clave para realizar una firma con formato XAdES-EPES es establecer formato XAdES-BES en el objeto DataToSign y también explicitar la política a aplicar:
dataToSign.setXadesFormat(EnumFormatoFirma.XAdES_BES);
dataToSign.setPolicyKey(POLICY_TO_APPLY);
Como se puede ver, la clave de la política a aplicar se define como constante en la propia clase. Además, dicha política deberá estar definida en el fichero de políticas (META-INF/xades/policy.properties), cuyo contenido podría ser el siguiente:
# En este fichero se indica qué clases son las encargadas de validar policies
# específicas
# Formato:
# <clave>=<clase>
# donde clave puede ser cualquier string que no contenga un código especial
# (por ejemplo un hash en hexadecimal de la policy), y clase es la clase
# que implementa el interfaz es.mityc.firmaJava.policy.IValidacionPolicy
implied=es.mityc.javasign.xml.xades.policy.PolicyImplied
En el caso de que se desee usar otra política, habría que crear una clase que implemente la interfaz IFirmaPolicy (interfaz que forma parte de la librería MITyCLibAPI del proyecto de Componentes), definirla en el fichero de políticas y usar la clave asociada (mediante la llamada al método setPolicyKey del objeto DataToSign.
En cuanto al método createDataToSign() de la clase GenericXMLSignature no es necesario sobrescribirlo puesto que con la implementación original es suficiente.