Ejemplo de firma XAdES T - gdiazs/MITyCLib GitHub Wiki

El objetivo de este ejemplo es mostrar los pasos necesarios para realizar una firma XAdES-T. 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-T 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: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:UnsignedProperties Id="Signature558204-UnsignedProperties307265">
                    <etsi:UnsignedSignatureProperties>
                        <etsi:SignatureTimeStamp Id="SelloTiempo915050">
                            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
                            <etsi:EncapsulatedTimeStamp Id="SelloTiempo-Token495737"><!-- Sello de tiempo en Base64 --></etsi:EncapsulatedTimeStamp>
                        </etsi:SignatureTimeStamp>
                    </etsi:UnsignedSignatureProperties>
                </etsi:UnsignedProperties>
            </etsi:QualifyingProperties>
        </ds:Object>
    </ds:Signature>
</documento>

Si se compara esta firma con la firma del ejemplo XAdES-BES (o con el ejemplo XAdES-EPES, ya que son iguales a excepción de la política explícita, que no es obligatoria) se puede observar que lo que aporta sobre ella es que aparece un Timestamp (tag etsi:SignatureTimeStamp dentro de las UnsignedSignatureProperties) que protege la firma contra el repudio.

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-T. 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_T);
    dataToSign.setTimeStampGenerator(new HTTPTimeStampGenerator(URL_TSA, TSPAlgoritmos.SHA1));
    dataToSign.setEsquema(XAdESSchemas.XAdES_132);
    dataToSign.setXMLEncoding("UTF-8");
    dataToSign.addClaimedRol(new SimpleClaimedRole("Rol de firma"));
    dataToSign.setEnveloped(true);
    Document docToSign = getDocument(RESOURCE_TO_SIGN);
    dataToSign.setDocument(docToSign);
    dataToSign.addObject(new ObjectToSign(new AllXMLToSign(), "Documento de ejemplo", null, "text/xml", null));
    return dataToSign;
}

Como se puede ver, el código es similar al mostrado en el ejemplo de firma Enveloped. La clave para elegir el formato XAdES-T es establecerlo en el objeto DataToSign:

dataToSign.setXadesFormat(EnumFormatoFirma.XAdES_T);

Por último, puesto que se trata de una firma que requiere de la generación de sellos de tiempo, es necesario establecer el generador de sellos de tiempo a utilizar en el objeto DataToSign. El generador de sellos de tiempo debe ser una instancia de la interfaz ITimeStampGenerator de la librería MITyCLibAPI. En este caso, puesto que las peticiones de sellos de tiempo se realizarán mediante protocolo HTTP(s), se utiliza la clase HTTPTimeStampGenerator de la librería MITyCLibTSA:

dataToSign.setTimeStampGenerator(new HTTPTimeStampGenerator(URL_TSA, TSPAlgoritmos.SHA1));  

Como se puede ver, la TSA a utilizar se define como una constante en la propia clase.

⚠️ **GitHub.com Fallback** ⚠️