/*
* XAdES4j - A Java library for generation and verification of XAdES signatures.
* Copyright (C) 2010 Luis Goncalves.
*
* XAdES4j is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or any later version.
*
* XAdES4j 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 XAdES4j. If not, see <http://www.gnu.org/licenses/>.
*/
package xades4j.production;
import xades4j.algorithms.Algorithm;
import com.google.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Element;
import xades4j.properties.CompleteCertificateRefsProperty;
import xades4j.properties.CompleteRevocationRefsProperty;
import xades4j.properties.QualifyingProperty;
import xades4j.properties.SigAndRefsTimeStampProperty;
import xades4j.properties.SignatureTimeStampProperty;
import xades4j.properties.data.BaseXAdESTimeStampData;
import xades4j.properties.data.SigAndRefsTimeStampData;
import xades4j.providers.AlgorithmsProviderEx;
import xades4j.providers.TimeStampTokenProvider;
import xades4j.providers.TimeStampTokenProvider.TimeStampTokenRes;
import xades4j.utils.CannotAddDataToDigestInputException;
import xades4j.utils.DOMHelper;
import xades4j.utils.TimeStampDigestInput;
import xades4j.utils.TimeStampDigestInputFactory;
/**
* Assumes that all the needed input elements are already in the signature.
* @author Luís
*/
class DataGenSigAndRefsTimeStamp extends DataGenBaseTimeStamp<SigAndRefsTimeStampProperty>
{
@Inject
public DataGenSigAndRefsTimeStamp(
AlgorithmsProviderEx algorithmsProvider,
TimeStampTokenProvider timeStampTokenProvider,
TimeStampDigestInputFactory timeStampDigestInputFactory)
{
super(algorithmsProvider, timeStampTokenProvider, timeStampDigestInputFactory);
}
@Override
protected void addPropSpecificTimeStampInput(
SigAndRefsTimeStampProperty prop,
TimeStampDigestInput digestInput,
PropertiesDataGenerationContext ctx) throws CannotAddDataToDigestInputException, PropertyDataGenerationException
{
Element unsignedSigPropsElem = DOMHelper.getFirstDescendant(
ctx.getTargetXmlSignature().getElement(),
QualifyingProperty.XADES_XMLNS, QualifyingProperty.UNSIGNED_SIGNATURE_PROPS_TAG);
if (null == unsignedSigPropsElem)
throw new PropertyDataGenerationException(prop, "no unsigned signature properties to get inputs");
/**
* This property contains a time-stamp token that covers the following data
* objects: {@code ds:SignatureValue} element, all present {@code SignatureTimeStamp}
* elements, {@code CompleteCertificateRefs}, {@code CompleteRevocationRefs}, and
* when present, {@code AttributeCertificateRefs} and {@code AttributeRevocationRefs}.
*
* "Those (...) that appear before SigAndRefsTimeStamp, in their order of
* appearance within the UnsignedSignatureProperties element."
*/
Map<String, Integer> elegiblePropsCnt = new HashMap<String, Integer>(5);
elegiblePropsCnt.put(CompleteCertificateRefsProperty.PROP_NAME, 0);
elegiblePropsCnt.put(CompleteRevocationRefsProperty.PROP_NAME, 0);
elegiblePropsCnt.put(SignatureTimeStampProperty.PROP_NAME, 0);
elegiblePropsCnt.put("AttributeCertificateRefs", 0);
elegiblePropsCnt.put("AttributeRevocationRefs", 0);
try
{
// SignatureValue.
Element e = DOMHelper.getFirstDescendant(
ctx.getTargetXmlSignature().getElement(),
Constants.SignatureSpecNS, Constants._TAG_SIGNATUREVALUE);
digestInput.addNode(e);
e = DOMHelper.getFirstChildElement(unsignedSigPropsElem);
// UnsignedProperties shouldn't be empty!
do
{
Integer pCnt = elegiblePropsCnt.get(e.getLocalName());
if (pCnt != null)
{
elegiblePropsCnt.put(e.getLocalName(), pCnt += 1);
digestInput.addNode(e);
}
} while ((e = DOMHelper.getNextSiblingElement(e)) != null);
// SignatureTimeStamp has to be present.
if (elegiblePropsCnt.get(SignatureTimeStampProperty.PROP_NAME) == 0)
throw new PropertyDataGenerationException(prop, "no signature time-stamps for input");
// CompleteCertificateRefs has to be present.
if (elegiblePropsCnt.get(CompleteCertificateRefsProperty.PROP_NAME) != 1)
throw new PropertyDataGenerationException(prop, "no CompleteCertificateRefs for input");
// CompleteRevocationRefs has to be present.
if (elegiblePropsCnt.get(CompleteRevocationRefsProperty.PROP_NAME) != 1)
throw new PropertyDataGenerationException(prop, "no CompleteRevocationRefs for input");
} catch (CannotAddDataToDigestInputException ex)
{
throw new PropertyDataGenerationException(prop, "cannot create timestamp input", ex);
}
}
@Override
protected BaseXAdESTimeStampData createPropDataObj(
SigAndRefsTimeStampProperty prop,
Algorithm c14n,
TimeStampTokenRes tsTknRes,
PropertiesDataGenerationContext ctx)
{
prop.setTime(tsTknRes.timeStampTime);
return new SigAndRefsTimeStampData(c14n, tsTknRes.encodedTimeStampToken);
}
}