/*
* eID Applet Project.
* Copyright (C) 2010 FedICT.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
package be.fedict.eid.applet.service.signer.facets;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CRLException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLObject;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.transform.TransformerException;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.apache.xml.security.utils.Constants;
import org.apache.xpath.XPathAPI;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.ocsp.ResponderID;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.ocsp.BasicOCSPResp;
import org.bouncycastle.ocsp.OCSPException;
import org.bouncycastle.ocsp.OCSPResp;
import org.bouncycastle.ocsp.RespID;
import org.joda.time.DateTime;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import be.fedict.eid.applet.service.signer.DigestAlgo;
import be.fedict.eid.applet.service.signer.SignatureFacet;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CRLIdentifierType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CRLRefType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CRLRefsType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CRLValuesType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CertIDListType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CertIDType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CertificateValuesType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CompleteCertificateRefsType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.CompleteRevocationRefsType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.DigestAlgAndValueType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.EncapsulatedPKIDataType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.OCSPIdentifierType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.OCSPRefType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.OCSPRefsType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.OCSPValuesType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.ObjectFactory;
import be.fedict.eid.applet.service.signer.jaxb.xades132.ResponderIDType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.RevocationValuesType;
import be.fedict.eid.applet.service.signer.jaxb.xades132.XAdESTimeStampType;
import be.fedict.eid.applet.service.signer.jaxb.xades141.ValidationDataType;
import be.fedict.eid.applet.service.signer.jaxb.xmldsig.CanonicalizationMethodType;
import be.fedict.eid.applet.service.signer.time.TimeStampService;
/**
* XAdES-X-L v1.4.1 signature facet. This signature facet implementation will
* upgrade a given XAdES-BES/EPES signature to XAdES-X-L.
*
* We don't inherit from XAdESSignatureFacet as we also want to be able to use
* this facet out of the context of a signature creation. This signature facet
* assumes that the signature is already XAdES-BES/EPES compliant.
*
* This implementation has been tested against an implementation that
* participated multiple ETSI XAdES plugtests.
*
* @author Frank Cornelis
* @see XAdESSignatureFacet
*/
public class XAdESXLSignatureFacet implements SignatureFacet {
private static final Log LOG = LogFactory.getLog(XAdESXLSignatureFacet.class);
public static final String XADES_NAMESPACE = "http://uri.etsi.org/01903/v1.3.2#";
public static final String XADES141_NAMESPACE = "http://uri.etsi.org/01903/v1.4.1#";
private Element nsElement;
private final ObjectFactory objectFactory;
private final be.fedict.eid.applet.service.signer.jaxb.xades141.ObjectFactory xades141ObjectFactory;
private final be.fedict.eid.applet.service.signer.jaxb.xmldsig.ObjectFactory xmldsigObjectFactory;
private final TimeStampService timeStampService;
private String c14nAlgoId;
private final Marshaller marshaller;
private final RevocationDataService revocationDataService;
private final CertificateFactory certificateFactory;
private final DatatypeFactory datatypeFactory;
private final DigestAlgo digestAlgorithm;
static {
Init.init();
}
/**
* Convenience constructor.
*
* @param timeStampService
* the time-stamp service used for XAdES-T and XAdES-X.
* @param revocationDataService
* the optional revocation data service used for XAdES-C and
* XAdES-X-L. When <code>null</code> the signature will be
* limited to XAdES-T only.
*/
public XAdESXLSignatureFacet(TimeStampService timeStampService, RevocationDataService revocationDataService) {
this(timeStampService, revocationDataService, DigestAlgo.SHA1);
}
/**
* Main constructor.
*
* @param timeStampService
* the time-stamp service used for XAdES-T and XAdES-X.
* @param revocationDataService
* the optional revocation data service used for XAdES-C and
* XAdES-X-L. When <code>null</code> the signature will be
* limited to XAdES-T only.
* @param digestAlgorithm
* the digest algorithm to be used for construction of the
* XAdES-X-L elements.
*/
public XAdESXLSignatureFacet(TimeStampService timeStampService, RevocationDataService revocationDataService,
DigestAlgo digestAlgorithm) {
this.objectFactory = new ObjectFactory();
this.c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
this.digestAlgorithm = digestAlgorithm;
this.timeStampService = timeStampService;
this.revocationDataService = revocationDataService;
this.xmldsigObjectFactory = new be.fedict.eid.applet.service.signer.jaxb.xmldsig.ObjectFactory();
this.xades141ObjectFactory = new be.fedict.eid.applet.service.signer.jaxb.xades141.ObjectFactory();
try {
JAXBContext context = JAXBContext
.newInstance(be.fedict.eid.applet.service.signer.jaxb.xades141.ObjectFactory.class);
this.marshaller = context.createMarshaller();
this.marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
this.marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new XAdESNamespacePrefixMapper());
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
try {
this.certificateFactory = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
throw new RuntimeException("X509 JCA error: " + e.getMessage(), e);
}
try {
this.datatypeFactory = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
throw new RuntimeException("datatype config error: " + e.getMessage(), e);
}
}
public void setCanonicalizerAlgorithm(String c14nAlgoId) {
this.c14nAlgoId = c14nAlgoId;
}
private Node findSingleNode(Node baseNode, String xpathExpression) {
if (null == this.nsElement) {
this.nsElement = createNamespaceElement(baseNode);
}
return findSingleNode(baseNode, xpathExpression, this.nsElement);
}
public static Node findSingleNode(Node baseNode, String xpathExpression, Element nsElement) {
try {
Node node = XPathAPI.selectSingleNode(baseNode, xpathExpression, nsElement);
return node;
} catch (TransformerException e) {
throw new RuntimeException("XPath error: " + e.getMessage(), e);
}
}
public static NodeList getNodes(Node baseNode, String xpathExpression, Element nsElement) {
try {
NodeList nodeList = XPathAPI.selectNodeList(baseNode, xpathExpression, nsElement);
return nodeList;
} catch (TransformerException e) {
throw new RuntimeException("XPath error: " + e.getMessage(), e);
}
}
public void postSign(Element signatureElement, List<X509Certificate> signingCertificateChain) {
LOG.debug("XAdES-X-L post sign phase");
// check for XAdES-BES
Element qualifyingPropertiesElement = (Element) findSingleNode(signatureElement,
"ds:Object/xades:QualifyingProperties");
if (null == qualifyingPropertiesElement) {
throw new IllegalArgumentException("no XAdES-BES extension present");
}
// create basic XML container structure
Document document = signatureElement.getOwnerDocument();
String xadesNamespacePrefix;
if (null != qualifyingPropertiesElement.getPrefix()) {
xadesNamespacePrefix = qualifyingPropertiesElement.getPrefix() + ":";
} else {
xadesNamespacePrefix = "";
}
Element unsignedPropertiesElement = (Element) findSingleNode(qualifyingPropertiesElement,
"xades:UnsignedProperties");
if (null == unsignedPropertiesElement) {
unsignedPropertiesElement = document.createElementNS(XADES_NAMESPACE,
xadesNamespacePrefix + "UnsignedProperties");
qualifyingPropertiesElement.appendChild(unsignedPropertiesElement);
}
Element unsignedSignaturePropertiesElement = (Element) findSingleNode(unsignedPropertiesElement,
"xades:UnsignedSignatureProperties");
if (null == unsignedSignaturePropertiesElement) {
unsignedSignaturePropertiesElement = document.createElementNS(XADES_NAMESPACE,
xadesNamespacePrefix + "UnsignedSignatureProperties");
unsignedPropertiesElement.appendChild(unsignedSignaturePropertiesElement);
}
// create the XAdES-T time-stamp
Node signatureValueNode = findSingleNode(signatureElement, "ds:SignatureValue");
RevocationData tsaRevocationDataXadesT = new RevocationData();
LOG.debug("creating XAdES-T time-stamp");
XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp(Collections.singletonList(signatureValueNode),
tsaRevocationDataXadesT, this.c14nAlgoId, this.timeStampService, this.objectFactory,
this.xmldsigObjectFactory);
// marshal the XAdES-T extension
try {
this.marshaller.marshal(this.objectFactory.createSignatureTimeStamp(signatureTimeStamp),
unsignedSignaturePropertiesElement);
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
// xadesv141::TimeStampValidationData
if (tsaRevocationDataXadesT.hasRevocationDataEntries()) {
ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT);
try {
this.marshaller.marshal(this.xades141ObjectFactory.createTimeStampValidationData(validationData),
unsignedSignaturePropertiesElement);
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
}
if (null == this.revocationDataService) {
/*
* Without revocation data service we cannot construct the XAdES-C
* extension.
*/
return;
}
// XAdES-C: complete certificate refs
CompleteCertificateRefsType completeCertificateRefs = this.objectFactory.createCompleteCertificateRefsType();
CertIDListType certIdList = this.objectFactory.createCertIDListType();
completeCertificateRefs.setCertRefs(certIdList);
List<CertIDType> certIds = certIdList.getCert();
for (int certIdx = 1; certIdx < signingCertificateChain.size(); certIdx++) {
/*
* We skip the signing certificate itself according to section
* 4.4.3.2 of the XAdES 1.4.1 specification.
*/
X509Certificate certificate = signingCertificateChain.get(certIdx);
CertIDType certId = XAdESSignatureFacet.getCertID(certificate, this.objectFactory,
this.xmldsigObjectFactory, this.digestAlgorithm, false);
certIds.add(certId);
}
// XAdES-C: complete revocation refs
CompleteRevocationRefsType completeRevocationRefs = this.objectFactory.createCompleteRevocationRefsType();
RevocationData revocationData = this.revocationDataService.getRevocationData(signingCertificateChain);
if (revocationData.hasCRLs()) {
CRLRefsType crlRefs = this.objectFactory.createCRLRefsType();
completeRevocationRefs.setCRLRefs(crlRefs);
List<CRLRefType> crlRefList = crlRefs.getCRLRef();
List<byte[]> crls = revocationData.getCRLs();
for (byte[] encodedCrl : crls) {
CRLRefType crlRef = this.objectFactory.createCRLRefType();
crlRefList.add(crlRef);
X509CRL crl;
try {
crl = (X509CRL) this.certificateFactory.generateCRL(new ByteArrayInputStream(encodedCrl));
} catch (CRLException e) {
throw new RuntimeException("CRL parse error: " + e.getMessage(), e);
}
CRLIdentifierType crlIdentifier = this.objectFactory.createCRLIdentifierType();
crlRef.setCRLIdentifier(crlIdentifier);
String issuerName;
try {
issuerName = PrincipalUtil.getIssuerX509Principal(crl).getName().replace(",", ", ");
} catch (CRLException e) {
throw new RuntimeException("CRL encoding error: " + e.getMessage(), e);
}
crlIdentifier.setIssuer(issuerName);
crlIdentifier.setIssueTime(this.datatypeFactory
.newXMLGregorianCalendar(new DateTime(crl.getThisUpdate()).toGregorianCalendar()));
crlIdentifier.setNumber(getCrlNumber(crl));
DigestAlgAndValueType digestAlgAndValue = XAdESSignatureFacet.getDigestAlgAndValue(encodedCrl,
this.objectFactory, this.xmldsigObjectFactory, this.digestAlgorithm);
crlRef.setDigestAlgAndValue(digestAlgAndValue);
}
}
if (revocationData.hasOCSPs()) {
OCSPRefsType ocspRefs = this.objectFactory.createOCSPRefsType();
completeRevocationRefs.setOCSPRefs(ocspRefs);
List<OCSPRefType> ocspRefList = ocspRefs.getOCSPRef();
List<byte[]> ocsps = revocationData.getOCSPs();
for (byte[] ocsp : ocsps) {
OCSPRefType ocspRef = this.objectFactory.createOCSPRefType();
ocspRefList.add(ocspRef);
DigestAlgAndValueType digestAlgAndValue = XAdESSignatureFacet.getDigestAlgAndValue(ocsp,
this.objectFactory, this.xmldsigObjectFactory, this.digestAlgorithm);
ocspRef.setDigestAlgAndValue(digestAlgAndValue);
OCSPIdentifierType ocspIdentifier = this.objectFactory.createOCSPIdentifierType();
ocspRef.setOCSPIdentifier(ocspIdentifier);
OCSPResp ocspResp;
try {
ocspResp = new OCSPResp(ocsp);
} catch (IOException e) {
throw new RuntimeException("OCSP decoding error: " + e.getMessage(), e);
}
Object ocspResponseObject;
try {
ocspResponseObject = ocspResp.getResponseObject();
} catch (OCSPException e) {
throw new RuntimeException("OCSP error: " + e.getMessage(), e);
}
BasicOCSPResp basicOcspResp = (BasicOCSPResp) ocspResponseObject;
Date producedAt = basicOcspResp.getProducedAt();
ocspIdentifier.setProducedAt(
this.datatypeFactory.newXMLGregorianCalendar(new DateTime(producedAt).toGregorianCalendar()));
ResponderIDType responderId = this.objectFactory.createResponderIDType();
ocspIdentifier.setResponderID(responderId);
RespID respId = basicOcspResp.getResponderId();
ResponderID ocspResponderId = respId.toASN1Object();
DERTaggedObject derTaggedObject = (DERTaggedObject) ocspResponderId.toASN1Object();
if (2 == derTaggedObject.getTagNo()) {
ASN1OctetString keyHashOctetString = (ASN1OctetString) derTaggedObject.getObject();
responderId.setByKey(keyHashOctetString.getOctets());
} else {
X509Name name = X509Name.getInstance(derTaggedObject.getObject());
responderId.setByName(name.toString());
}
}
}
// marshal XAdES-C
NodeList unsignedSignaturePropertiesNodeList = ((Element) qualifyingPropertiesElement)
.getElementsByTagNameNS(XADES_NAMESPACE, "UnsignedSignatureProperties");
Node unsignedSignaturePropertiesNode = unsignedSignaturePropertiesNodeList.item(0);
try {
this.marshaller.marshal(this.objectFactory.createCompleteCertificateRefs(completeCertificateRefs),
unsignedSignaturePropertiesNode);
this.marshaller.marshal(this.objectFactory.createCompleteRevocationRefs(completeRevocationRefs),
unsignedSignaturePropertiesNode);
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
// XAdES-X Type 1 timestamp
List<Node> timeStampNodesXadesX1 = new LinkedList<Node>();
timeStampNodesXadesX1.add(signatureValueNode);
Node signatureTimeStampNode = findSingleNode(unsignedSignaturePropertiesNode, "xades:SignatureTimeStamp");
timeStampNodesXadesX1.add(signatureTimeStampNode);
Node completeCertificateRefsNode = findSingleNode(unsignedSignaturePropertiesNode,
"xades:CompleteCertificateRefs");
timeStampNodesXadesX1.add(completeCertificateRefsNode);
Node completeRevocationRefsNode = findSingleNode(unsignedSignaturePropertiesNode,
"xades:CompleteRevocationRefs");
timeStampNodesXadesX1.add(completeRevocationRefsNode);
RevocationData tsaRevocationDataXadesX1 = new RevocationData();
LOG.debug("creating XAdES-X time-stamp");
XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp(timeStampNodesXadesX1, tsaRevocationDataXadesX1,
this.c14nAlgoId, this.timeStampService, this.objectFactory, this.xmldsigObjectFactory);
ValidationDataType timeStampXadesX1ValidationData;
if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) {
timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1);
} else {
timeStampXadesX1ValidationData = null;
}
// marshal XAdES-X
try {
this.marshaller.marshal(this.objectFactory.createSigAndRefsTimeStamp(timeStampXadesX1),
unsignedSignaturePropertiesNode);
if (null != timeStampXadesX1ValidationData) {
this.marshaller.marshal(
this.xades141ObjectFactory.createTimeStampValidationData(timeStampXadesX1ValidationData),
unsignedSignaturePropertiesNode);
}
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
// XAdES-X-L
CertificateValuesType certificateValues = this.objectFactory.createCertificateValuesType();
List<Object> certificateValuesList = certificateValues.getEncapsulatedX509CertificateOrOtherCertificate();
for (X509Certificate certificate : signingCertificateChain) {
EncapsulatedPKIDataType encapsulatedPKIDataType = this.objectFactory.createEncapsulatedPKIDataType();
try {
encapsulatedPKIDataType.setValue(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new RuntimeException("certificate encoding error: " + e.getMessage(), e);
}
certificateValuesList.add(encapsulatedPKIDataType);
}
RevocationValuesType revocationValues = createRevocationValues(revocationData);
// marshal XAdES-X-L
try {
this.marshaller.marshal(this.objectFactory.createCertificateValues(certificateValues),
unsignedSignaturePropertiesNode);
this.marshaller.marshal(this.objectFactory.createRevocationValues(revocationValues),
unsignedSignaturePropertiesNode);
} catch (JAXBException e) {
throw new RuntimeException("JAXB error: " + e.getMessage(), e);
}
}
public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
byte[] c14nValue = null;
try {
for (Node node : nodeList) {
/*
* Re-initialize the c14n else the namespaces will get cached
* and will be missing from the c14n resulting nodes.
*/
Canonicalizer c14n;
try {
c14n = Canonicalizer.getInstance(c14nAlgoId);
} catch (InvalidCanonicalizerException e) {
throw new RuntimeException("c14n algo error: " + e.getMessage(), e);
}
c14nValue = ArrayUtils.addAll(c14nValue, c14n.canonicalizeSubtree(node));
}
} catch (CanonicalizationException e) {
throw new RuntimeException("c14n error: " + e.getMessage(), e);
}
return c14nValue;
}
public static Element createNamespaceElement(Node documentNode) {
Document document = documentNode.getOwnerDocument();
Element nsElement = document.createElement("nsElement");
nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xades", XADES_NAMESPACE);
return nsElement;
}
public void preSign(XMLSignatureFactory signatureFactory, Document document, String signatureId,
List<X509Certificate> signingCertificateChain, List<Reference> references, List<XMLObject> objects)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
// nothing to do here
}
private BigInteger getCrlNumber(X509CRL crl) {
byte[] crlNumberExtensionValue = crl.getExtensionValue(X509Extensions.CRLNumber.getId());
if (null == crlNumberExtensionValue) {
return null;
}
try {
ASN1InputStream asn1InputStream = new ASN1InputStream(crlNumberExtensionValue);
ASN1OctetString octetString = (ASN1OctetString) asn1InputStream.readObject();
byte[] octets = octetString.getOctets();
DERInteger integer = (DERInteger) new ASN1InputStream(octets).readObject();
BigInteger crlNumber = integer.getPositiveValue();
return crlNumber;
} catch (IOException e) {
throw new RuntimeException("I/O error: " + e.getMessage(), e);
}
}
public static XAdESTimeStampType createXAdESTimeStamp(List<Node> nodeList, RevocationData revocationData,
String c14nAlgoId, TimeStampService timeStampService, ObjectFactory objectFactory,
be.fedict.eid.applet.service.signer.jaxb.xmldsig.ObjectFactory xmldsigObjectFactory) {
byte[] c14nSignatureValueElement = getC14nValue(nodeList, c14nAlgoId);
return createXAdESTimeStamp(c14nSignatureValueElement, revocationData, c14nAlgoId, timeStampService,
objectFactory, xmldsigObjectFactory);
}
public static XAdESTimeStampType createXAdESTimeStamp(byte[] data, RevocationData revocationData, String c14nAlgoId,
TimeStampService timeStampService, ObjectFactory objectFactory,
be.fedict.eid.applet.service.signer.jaxb.xmldsig.ObjectFactory xmldsigObjectFactory) {
// create the time-stamp
byte[] timeStampToken;
try {
timeStampToken = timeStampService.timeStamp(data, revocationData);
} catch (Exception e) {
throw new RuntimeException("error while creating a time-stamp: " + e.getMessage(), e);
}
// create a XAdES time-stamp container
XAdESTimeStampType xadesTimeStamp = objectFactory.createXAdESTimeStampType();
CanonicalizationMethodType c14nMethod = xmldsigObjectFactory.createCanonicalizationMethodType();
c14nMethod.setAlgorithm(c14nAlgoId);
xadesTimeStamp.setCanonicalizationMethod(c14nMethod);
xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString());
// embed the time-stamp
EncapsulatedPKIDataType encapsulatedTimeStamp = objectFactory.createEncapsulatedPKIDataType();
encapsulatedTimeStamp.setValue(timeStampToken);
encapsulatedTimeStamp.setId("time-stamp-token-" + UUID.randomUUID().toString());
List<Object> timeStampContent = xadesTimeStamp.getEncapsulatedTimeStampOrXMLTimeStamp();
timeStampContent.add(encapsulatedTimeStamp);
return xadesTimeStamp;
}
private ValidationDataType createValidationData(RevocationData revocationData) {
ValidationDataType validationData = this.xades141ObjectFactory.createValidationDataType();
RevocationValuesType revocationValues = createRevocationValues(revocationData);
validationData.setRevocationValues(revocationValues);
return validationData;
}
private RevocationValuesType createRevocationValues(RevocationData revocationData) {
RevocationValuesType revocationValues = this.objectFactory.createRevocationValuesType();
if (revocationData.hasCRLs()) {
CRLValuesType crlValues = this.objectFactory.createCRLValuesType();
revocationValues.setCRLValues(crlValues);
List<EncapsulatedPKIDataType> encapsulatedCrlValues = crlValues.getEncapsulatedCRLValue();
List<byte[]> crls = revocationData.getCRLs();
for (byte[] crl : crls) {
EncapsulatedPKIDataType encapsulatedCrlValue = this.objectFactory.createEncapsulatedPKIDataType();
encapsulatedCrlValue.setValue(crl);
encapsulatedCrlValues.add(encapsulatedCrlValue);
}
}
if (revocationData.hasOCSPs()) {
OCSPValuesType ocspValues = this.objectFactory.createOCSPValuesType();
revocationValues.setOCSPValues(ocspValues);
List<EncapsulatedPKIDataType> encapsulatedOcspValues = ocspValues.getEncapsulatedOCSPValue();
List<byte[]> ocsps = revocationData.getOCSPs();
for (byte[] ocsp : ocsps) {
EncapsulatedPKIDataType encapsulatedOcspValue = this.objectFactory.createEncapsulatedPKIDataType();
encapsulatedOcspValue.setValue(ocsp);
encapsulatedOcspValues.add(encapsulatedOcspValue);
}
}
return revocationValues;
}
}