Skip to content

Commit

Permalink
Merge pull request #304 from luisgoncalves/iss259-add-ids-ondemand
Browse files Browse the repository at this point in the history
Add element IDs on demand instead of upfront
  • Loading branch information
luisgoncalves authored Sep 14, 2024
2 parents 5278408 + 1e390f8 commit a8c3c1f
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 364 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public PropertyDataObject generatePropertyData(
{
// The ObjectReference refers the Reference element. This assumes
// that the QualifyingProperties are in the signature's document.
commTypeData.addObjReferences('#' + ctx.getReference(obj).getId());
commTypeData.addObjReferences('#' + ctx.ensureElementId(ctx.getReference(obj)));
}

commTypeData.setQualifiers(prop.getQualifiers());
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/xades4j/production/DataGenCounterSig.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,11 @@ public PropertyDataObject generatePropertyData(
try
{
// Rerence to the ds:SignatureValue element. This assumes that the
// QualifyingProperties are in the signature's document and that the
// SignatureValue element has an Id.
// QualifyingProperties are in the signature's document.
Element sigValueElem = DOMHelper.getFirstDescendant(
ctx.getTargetXmlSignature().getElement(),
Constants.SignatureSpecNS, Constants._TAG_SIGNATUREVALUE);
String sigValueId = sigValueElem.getAttribute(Constants._ATT_ID);
String sigValueId = ctx.ensureElementId(sigValueElem);
DataObjectReference sigValueRef = new DataObjectReference('#' + sigValueId)
.withType(CounterSignatureProperty.COUNTER_SIGNATURE_TYPE_URI);

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/xades4j/production/DataGenDataObjFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public PropertyDataObject generatePropertyData(
// corresponding with the data object qualified by this property.
// This assumes that the QualifyingProperties are in the signature's document.
DataObjectDesc targetDataObjInfo = prop.getTargetDataObjects().iterator().next();
String objRef = '#' + ctx.getReference(targetDataObjInfo).getId();
String objRef = '#' + ctx.ensureElementId(ctx.getReference(targetDataObjInfo));

DataObjectFormatData dataObjFormatData = new DataObjectFormatData(objRef);
dataObjFormatData.setMimeType(prop.getMimeType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ protected BaseXAdESTimeStampData createPropDataObj(
for (DataObjectDesc dataObj : targetDataObjs)
{
Reference r = ctx.getReference(dataObj);
includes.add('#' + r.getId());
includes.add('#' + ctx.ensureElementId(r));
}

prop.setTime(tsTknRes.timeStampTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.xml.security.signature.Reference;
import org.apache.xml.security.signature.SignedInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import xades4j.XAdES4jXMLSigException;
Expand All @@ -32,6 +33,9 @@
import java.util.List;
import java.util.Map;

import static xades4j.production.SignerBES.idFor;
import static xades4j.utils.StringUtils.isNullOrEmptyString;

/**
* Context used during the generation of the properties low-level data (property
* data objects). Contains informations about the algorithms in use and the resources
Expand All @@ -45,19 +49,22 @@ public final class PropertiesDataGenerationContext
private final List<Reference> references;
private final Map<DataObjectDesc, Reference> referencesMappings;
private final Document sigDocument;
private final ElementIdGenerator idGenerator;
private XMLSignature targetXmlSignature;

/**
* A simple constructor to be used when only unsigned signature properties
* will be processed.
*
* @param targetXmlSignature the target signature
* @param idGenerator ID generator
*/
PropertiesDataGenerationContext(XMLSignature targetXmlSignature) throws XAdES4jXMLSigException
PropertiesDataGenerationContext(XMLSignature targetXmlSignature, ElementIdGenerator idGenerator) throws XAdES4jXMLSigException
{
this.targetXmlSignature = targetXmlSignature;
this.sigDocument = targetXmlSignature.getDocument();
this.referencesMappings = null;
this.idGenerator = idGenerator;

SignedInfo signedInfo = targetXmlSignature.getSignedInfo();
List<Reference> refs = new ArrayList<>(signedInfo.getLength());
Expand All @@ -83,10 +90,12 @@ public final class PropertiesDataGenerationContext
PropertiesDataGenerationContext(
Collection<DataObjectDesc> orderedDataObjs,
Map<DataObjectDesc, Reference> referencesMappings,
Document sigDocument)
Document sigDocument,
ElementIdGenerator idGenerator)
{
this.referencesMappings = referencesMappings;
this.sigDocument = sigDocument;
this.idGenerator = idGenerator;

List<Reference> orderedRefs = new ArrayList<>(orderedDataObjs.size());
for (DataObjectDesc dataObjDesc : orderedDataObjs)
Expand Down Expand Up @@ -120,6 +129,29 @@ public Reference getReference(DataObjectDesc dataObject)
return referencesMappings.get(dataObject);
}

public String ensureElementId(Reference element)
{
String id = element.getId();
if (isNullOrEmptyString(id))
{
id = idFor(element, idGenerator);
element.setId(id);
}

return id;
}

public String ensureElementId(Element element)
{
String id = element.getAttribute(Constants._ATT_ID);
if (isNullOrEmptyString(id))
{
id = idFor(element, idGenerator);
DOMHelper.setIdAsXmlId(element, id);
}
return id;
}

XMLSignature getTargetXmlSignature()
{
if (this.targetXmlSignature == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ else if (dataObjDesc instanceof EnvelopedManifest)

Transforms transforms = processTransforms(dataObjDesc, container.getDocument());

// Add the Reference. References need an ID because data object properties may refer them.
// Add the Reference
container.addDocument(
xmlSignature.getBaseURI(),
refUri,
Expand All @@ -209,7 +209,6 @@ else if (dataObjDesc instanceof EnvelopedManifest)
// SignedDataObjects and EnvelopedManifest don't allow repeated instances, so there's no
// need to check for duplicate entries on the map.
Reference ref = container.item(index);
ref.setId(idFor(ref, idGenerator));
referenceMappings.put(dataObjDesc, ref);
}

Expand Down
26 changes: 10 additions & 16 deletions src/main/java/xades4j/production/SignerBES.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,7 @@
*/
package xades4j.production;

import static xades4j.utils.CanonicalizerUtils.checkC14NAlgorithm;

import jakarta.inject.Inject;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.signature.Manifest;
import org.apache.xml.security.signature.ObjectContainer;
Expand Down Expand Up @@ -63,6 +53,14 @@
import xades4j.xml.marshalling.UnsignedPropertiesMarshaller;
import xades4j.xml.marshalling.algorithms.AlgorithmsParametersMarshallingProvider;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static xades4j.utils.CanonicalizerUtils.checkC14NAlgorithm;

/**
* Base logic for producing XAdES signatures (XAdES-BES).
*
Expand Down Expand Up @@ -233,7 +231,8 @@ public final XadesSignatureResult sign(
PropertiesDataGenerationContext propsDataGenCtx = new PropertiesDataGenerationContext(
signedDataObjects.getDataObjectsDescs(),
signedDataObjectsResult.referenceMappings,
signatureDocument);
signatureDocument,
idGenerator);
// Generate the signed properties data objects. The data objects structure
// is verifier in the process.
SigAndDataObjsPropertiesData signedPropsData = this.propsDataObjectsGenerator.generateSignedPropertiesData(
Expand Down Expand Up @@ -285,11 +284,6 @@ public final XadesSignatureResult sign(
{
throw new XAdES4jXMLSigException(ex.getMessage(), ex);
}
// Set the ds:SignatureValue id.
Element sigValueElem = DOMHelper.getFirstDescendant(
signature.getElement(),
Constants.SignatureSpecNS, Constants._TAG_SIGNATUREVALUE);
DOMHelper.setIdAsXmlId(sigValueElem, idFor(sigValueElem, idGenerator));

/* Marshal unsigned properties */
// Generate the unsigned properties data objects. The data objects structure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ class XadesSignatureFormatExtenderImpl implements XadesSignatureFormatExtender
{
Init.initXMLSec();
}

private final ElementIdGeneratorFactory idGeneratorFactory;
private final PropertiesDataObjectsGenerator propsDataObjectsGenerator;
private final UnsignedPropertiesMarshaller unsignedPropsMarshaller;

@Inject
XadesSignatureFormatExtenderImpl(
ElementIdGeneratorFactory idGeneratorFactory,
PropertiesDataObjectsGenerator propsDataObjectsGenerator,
UnsignedPropertiesMarshaller unsignedPropsMarshaller)
{
this.idGeneratorFactory = idGeneratorFactory;
this.propsDataObjectsGenerator = propsDataObjectsGenerator;
this.unsignedPropsMarshaller = unsignedPropsMarshaller;
}
Expand Down Expand Up @@ -76,10 +80,12 @@ public void enrichSignature(
DOMHelper.useIdAsXmlId(signedProps);
}

ElementIdGenerator idGenerator = idGeneratorFactory.create();

SigAndDataObjsPropertiesData propsData = propsDataObjectsGenerator.generateUnsignedPropertiesData(
props,
new PropertiesDataGenerationContext(sig));
new PropertiesDataGenerationContext(sig, idGenerator));

// A little style trick to have nice prefixes.
if(null == sig.getDocument().lookupPrefix(QualifyingProperty.XADESV141_XMLNS))
qualifProps.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xades141", QualifyingProperty.XADESV141_XMLNS);
Expand Down
Loading

0 comments on commit a8c3c1f

Please sign in to comment.