All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.europa.esig.dss.spi.x509.tsp.TimestampToken Maven / Gradle / Ivy

/**
 * DSS - Digital Signature Services
 * Copyright (C) 2015 European Commission, provided under the CEF programme
 * 

* This file is part of the "DSS - Digital Signature Services" project. *

* This library 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 2.1 of the License, or (at your option) any later version. *

* This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package eu.europa.esig.dss.spi.x509.tsp; import eu.europa.esig.dss.enumerations.ArchiveTimestampType; import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.enumerations.DigestMatcherType; import eu.europa.esig.dss.enumerations.EncryptionAlgorithm; import eu.europa.esig.dss.enumerations.EvidenceRecordTimestampType; import eu.europa.esig.dss.enumerations.SignatureAlgorithm; import eu.europa.esig.dss.enumerations.SignatureValidity; import eu.europa.esig.dss.enumerations.TimestampType; import eu.europa.esig.dss.model.DSSDocument; import eu.europa.esig.dss.model.DSSException; import eu.europa.esig.dss.model.DSSMessageDigest; import eu.europa.esig.dss.model.Digest; import eu.europa.esig.dss.model.ManifestFile; import eu.europa.esig.dss.model.ReferenceValidation; import eu.europa.esig.dss.model.identifier.TokenIdentifier; import eu.europa.esig.dss.model.scope.SignatureScope; import eu.europa.esig.dss.model.x509.CertificateToken; import eu.europa.esig.dss.model.x509.Token; import eu.europa.esig.dss.spi.DSSASN1Utils; import eu.europa.esig.dss.spi.DSSSecurityProvider; import eu.europa.esig.dss.spi.DSSUtils; import eu.europa.esig.dss.spi.x509.CandidatesForSigningCertificate; import eu.europa.esig.dss.spi.x509.CertificateRef; import eu.europa.esig.dss.spi.x509.SignerIdentifier; import eu.europa.esig.dss.spi.x509.evidencerecord.EvidenceRecord; import eu.europa.esig.dss.utils.Utils; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationStore; import org.bouncycastle.cms.SignerInformationVerifier; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; import org.bouncycastle.operator.OperatorException; import org.bouncycastle.tsp.TSPException; import org.bouncycastle.tsp.TimeStampToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.security.PublicKey; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Set; /** * SignedToken containing a TimeStamp. * */ @SuppressWarnings("serial") public class TimestampToken extends Token { private static final Logger LOG = LoggerFactory.getLogger(TimestampToken.class); /** * BouncyCastle representation of a TimeStamp Token */ private final TimeStampToken timeStamp; /** * Type of the timestamp relatively to the signature */ private final TimestampType timeStampType; /** * Certificate source extracted from the timestamp */ private final TimestampCertificateSource certificateSource; /** * CRL source extracted from the timestamp */ private final TimestampCRLSource crlSource; /** * OCSP source extracted from the timestamp */ private final TimestampOCSPSource ocspSource; /** * List of references to tokens covered (protected) by the timestamp */ private final List timestampedReferences; /** * Builds a time-stamp token unique identifier */ private TimestampIdentifierBuilder identifierBuilder; /** * Internal variables defining whether the timestamp has been validated */ private boolean processed = false; /** * Computed message-imprint */ private Digest messageImprint; /** * Defines whether the message-imprint has been found */ private boolean messageImprintData; /** * Defines whether the computed message-imprint is intact */ private Boolean messageImprintIntact = null; /** * In case of a detached timestamp */ private String filename; /** * Only present for detached timestamps; */ private List timestampScopes; /** * The timestamped manifest file, when applicable (ASiC with CAdES) */ private ManifestFile manifestFile; /** * In case of XAdES IndividualDataObjectsTimeStamp, Includes shall be specified */ private List timestampIncludes; /** * In case of an Evidence record time-stamp, contains references to */ private List referenceValidations; /** * Returns a list of detached evidence records covering the time-stamp, when applicable */ private List detachedEvidenceRecords; /** * Defines for archive timestamp its type. */ private ArchiveTimestampType archiveTimestampType; /** * Defines for an evidence record archive timestamp its type. */ private EvidenceRecordTimestampType evidenceRecordTimestampType; /** * This attribute is used for XAdES timestamps. It indicates the canonicalization method * used for message-imprint computation. *

* NOTE: Used for XAdES/JAdES only */ private String canonicalizationMethod; /** * Identifies a TSA issued the timestamp token *

* NOTE: Takes a value only for a successfully validated token */ private X500Principal tsaX500Principal; /** * Cached list of signing certificate candidates */ private CandidatesForSigningCertificate candidatesForSigningCertificate; /** * Contains validation status of the ats-hash-index(-v3) attribute. * NOTE: applicable only for CMS archive-time-stamp-v3 timestamps. */ private ArchiveTimestampHashIndexStatus hashIndexStatus; /** * Default constructor * * @param binaries byte array * @param type {@link TimestampType} * @throws TSPException if timestamp creation exception occurs * @throws IOException if IOException occurs * @throws CMSException if CMS data building exception occurs */ public TimestampToken(final byte[] binaries, final TimestampType type) throws TSPException, IOException, CMSException { this(binaries, type, new ArrayList<>()); } /** * Default constructor with timestamped references * * @param binaries byte array * @param type {@link TimestampType} * @param timestampedReferences a list of {@link TimestampedReference}s * @throws TSPException if timestamp creation exception occurs * @throws IOException if IOException occurs * @throws CMSException if CMS data building exception occurs */ public TimestampToken(final byte[] binaries, final TimestampType type, final List timestampedReferences) throws TSPException, IOException, CMSException { this(new CMSSignedData(binaries), type, timestampedReferences); } /** * Default constructor with timestamped references and identifier builder * * @param binaries byte array * @param type {@link TimestampType} * @param timestampedReferences a list of {@link TimestampedReference}s * @param identifierBuilder {@link TimestampIdentifierBuilder} * @throws TSPException if timestamp creation exception occurs * @throws IOException if IOException occurs * @throws CMSException if CMS data building exception occurs */ public TimestampToken(final byte[] binaries, final TimestampType type, final List timestampedReferences, final TimestampIdentifierBuilder identifierBuilder) throws TSPException, IOException, CMSException { this(new CMSSignedData(binaries), type, timestampedReferences, identifierBuilder); } /** * Constructor from CMS with timestamped references * * @param cms {@link CMSSignedData} * @param type {@link TimestampType} * @param timestampedReferences a list of {@link TimestampedReference}s * @throws TSPException if timestamp creation exception occurs * @throws IOException if IOException occurs */ public TimestampToken(final CMSSignedData cms, final TimestampType type, final List timestampedReferences) throws TSPException, IOException { this(new TimeStampToken(cms), type, timestampedReferences); } /** * Constructor from CMS with timestamped references and identifier builder * * @param cms {@link CMSSignedData} * @param type {@link TimestampType} * @param timestampedReferences a list of {@link TimestampedReference}s * @param identifierBuilder {@link TimestampIdentifierBuilder} * @throws TSPException if timestamp creation exception occurs * @throws IOException if IOException occurs */ public TimestampToken(final CMSSignedData cms, final TimestampType type, final List timestampedReferences, final TimestampIdentifierBuilder identifierBuilder) throws TSPException, IOException { this(new TimeStampToken(cms), type, timestampedReferences, identifierBuilder); } /** * Constructor with an indication of the timestamp type and time-stamped references. * The default constructor for {@code TimestampToken}. Builds an implementation independent identifier. * * @param timeStamp * {@code TimeStampToken} * @param type * {@code TimestampType} * @param timestampedReferences * timestamped references * timestamp comes from */ public TimestampToken(final TimeStampToken timeStamp, final TimestampType type, final List timestampedReferences) { this(timeStamp, type, timestampedReferences, null); } /** * Constructor with an indication of the timestamp type, time-stamped references and an identifier builder. * * @param timeStamp * {@code TimeStampToken} * @param type * {@code TimestampType} * @param timestampedReferences * timestamped references * timestamp comes from * @param identifierBuilder * {@link TimestampIdentifierBuilder} */ public TimestampToken(final TimeStampToken timeStamp, final TimestampType type, final List timestampedReferences, final TimestampIdentifierBuilder identifierBuilder) { this.timeStamp = timeStamp; this.timeStampType = type; this.certificateSource = new TimestampCertificateSource(timeStamp); this.ocspSource = new TimestampOCSPSource(timeStamp); this.crlSource = new TimestampCRLSource(timeStamp); this.timestampedReferences = timestampedReferences; this.identifierBuilder = identifierBuilder; } @Override public X500Principal getIssuerX500Principal() { return tsaX500Principal; } @Override public String getAbbreviation() { return timeStampType.name() + ": " + getDSSIdAsString() + ": " + DSSUtils.formatDateToRFC(timeStamp.getTimeStampInfo().getGenTime()); } /** * Returns {@code TimestampCertificateSource} for the timestamp * * @return {@link TimestampCertificateSource} */ public TimestampCertificateSource getCertificateSource() { return certificateSource; } /** * Returns {@code TimestampCRLSource} for the timestamp * * @return {@link TimestampCRLSource} */ public TimestampCRLSource getCRLSource() { return crlSource; } /** * Returns {@code TimestampOCSPSource} for the timestamp * * @return {@link TimestampOCSPSource} */ public TimestampOCSPSource getOCSPSource() { return ocspSource; } /** * Indicated if the signature is intact and the message-imprint matches the computed message-imprint. *

* NOTE: The method isSignedBy(CertificateToken) must be called before calling the method. * See {@code TimestampToken.isSignatureIntact()} for more details * * @return TRUE if the signature is cryptographically intact and message-imprint matches, FALSE otherwise */ @Override public boolean isValid() { return isSignatureIntact() && isMessageImprintDataFound() && isMessageImprintDataIntact() && areReferenceValidationsValid(); } /** * Checks if the timestamp token is signed by the given publicKey * * @param certificateToken * the candidate to be tested * @return true if this token is signed by the given public key */ @Override public synchronized boolean isSignedBy(final CertificateToken certificateToken) { if (publicKeyOfTheSigner != null) { return publicKeyOfTheSigner.equals(certificateToken.getPublicKey()); } else if (SignatureValidity.VALID == checkIsSignedBy(certificateToken)) { if (!isSelfSigned()) { this.publicKeyOfTheSigner = certificateToken.getPublicKey(); } return true; } return false; } @Override public synchronized boolean isSignedBy(final PublicKey publicKey) { throw new UnsupportedOperationException("Use method isSignedBy(certificateToken) for a TimestampToken validation!"); } /** * Checks if timestamp is signed by teh given certificate * * @param candidate {@link CertificateToken} * @return {@link SignatureValidity} */ protected SignatureValidity checkIsSignedBy(final CertificateToken candidate) { final X509CertificateHolder x509CertificateHolder = DSSASN1Utils.getX509CertificateHolder(candidate); if (timeStamp.getSID().match(x509CertificateHolder)) { SignerInformationVerifier signerInformationVerifier = getSignerInformationVerifier(candidate); // Try firstly to validate as a Timestamp and if that fails try to validate the // timestamp as a CMSSignedData if (isValidTimestamp(signerInformationVerifier) || isValidCMSSignedData(signerInformationVerifier)) { signatureValidity = SignatureValidity.VALID; this.tsaX500Principal = candidate.getSubject().getPrincipal(); SignerInformation signerInformation = timeStamp.toCMSSignedData().getSignerInfos().get(timeStamp.getSID()); if (EncryptionAlgorithm.RSASSA_PSS.getOid().equals(signerInformation.getEncryptionAlgOID())) { signatureAlgorithm = SignatureAlgorithm.forOidAndParams(signerInformation.getEncryptionAlgOID(), signerInformation.getEncryptionAlgParams()); } else { EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.forName(candidate.getPublicKey().getAlgorithm()); final AlgorithmIdentifier hashAlgorithm = signerInformation.getDigestAlgorithmID(); final DigestAlgorithm digestAlgorithm = DigestAlgorithm.forOID(hashAlgorithm.getAlgorithm().getId()); signatureAlgorithm = SignatureAlgorithm.getAlgorithm(encryptionAlgorithm, digestAlgorithm); } } else { signatureValidity = SignatureValidity.INVALID; } return signatureValidity; } return SignatureValidity.INVALID; } private boolean isValidTimestamp(SignerInformationVerifier signerInformationVerifier) { try { // Validate the timestamp, the signing certificate,... timeStamp.validate(signerInformationVerifier); return true; } catch (TSPException e) { if (LOG.isDebugEnabled()) { LOG.debug("Unable to validate timestamp token : ", e); } else { LOG.warn("Unable to validate timestamp token : {}", e.getMessage()); } signatureInvalidityReason = e.getClass().getSimpleName() + " : " + e.getMessage(); return false; } } private boolean isValidCMSSignedData(SignerInformationVerifier signerInformationVerifier) { try { // Only validate the cryptographic validity SignerInformationStore signerInfos = timeStamp.toCMSSignedData().getSignerInfos(); SignerInformation signerInformation = signerInfos.get(timeStamp.getSID()); return signerInformation.verify(signerInformationVerifier); } catch (CMSException e) { if (LOG.isDebugEnabled()) { LOG.debug("Unable to validate the related CMSSignedData : ", e); } else { LOG.warn("Unable to validate the related CMSSignedData : {}", e.getMessage()); } signatureInvalidityReason = e.getClass().getSimpleName() + " : " + e.getMessage(); return false; } } private SignerInformationVerifier getSignerInformationVerifier(final CertificateToken candidate) { try { final JcaSimpleSignerInfoVerifierBuilder verifier = new JcaSimpleSignerInfoVerifierBuilder(); verifier.setProvider(DSSSecurityProvider.getSecurityProviderName()); return verifier.build(candidate.getCertificate()); } catch (OperatorException e) { throw new DSSException("Unable to build an instance of SignerInformationVerifier", e); } } @Override protected SignatureValidity checkIsSignedBy(final PublicKey publicKey) { throw new UnsupportedOperationException("Use method checkIsSignedBy(certificateToken) for a TimestampToken validation!"); } /** * Checks if the {@code TimeStampToken} matches the signed data. * * @param timestampedData * a {@code DSSDocument} representing the timestamped data * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final DSSDocument timestampedData) { return matchData(timestampedData, false); } /** * Checks if the {@code TimeStampToken} matches the signed data. * * @param timestampedData * a {@code DSSDocument} representing the timestamped data * @param suppressMatchWarnings * if true the message imprint match warning logs are suppressed. * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final DSSDocument timestampedData, final boolean suppressMatchWarnings) { processed = true; messageImprintData = timestampedData != null; messageImprintIntact = false; if (!messageImprintData) { LOG.warn("Timestamped data not found !"); return false; } Digest currentMessageImprint = getMessageImprint(); byte[] computedDigest = timestampedData.getDigestValue(currentMessageImprint.getAlgorithm()); return matchData(computedDigest, suppressMatchWarnings); } /** * Checks if the {@code TimeStampToken} matches the message-imprint digest with warning enabled. * * @param messageDigest * {@code DSSMessageDigest} representing the message-imprint digest * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final DSSMessageDigest messageDigest) { return matchData(messageDigest, false); } /** * Checks if the {@code TimeStampToken} matches the message-imprint digest. * * @param messageDigest * {@code DSSMessageDigest} representing the message-imprint digest * @param suppressMatchWarnings * if true the message imprint match warning logs are suppressed. * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final DSSMessageDigest messageDigest, final boolean suppressMatchWarnings) { processed = true; if (messageDigest == null || messageDigest.isEmpty()) { messageImprintIntact = false; if (!suppressMatchWarnings) { LOG.warn("Invalid or incomplete message-digest has been provided for timestamp verification!"); } } else if (getDigestAlgorithm() != messageDigest.getAlgorithm()) { messageImprintIntact = false; if (!suppressMatchWarnings) { LOG.warn("DigestAlgorithm '{}' used in the provided message-digest does not match the one used " + "in the timestamp token '{}'!", messageDigest.getAlgorithm(), getDigestAlgorithm()); } } else { messageImprintIntact = matchData(messageDigest.getValue(), suppressMatchWarnings); } return messageImprintIntact; } /** * Checks if the {@code TimeStampToken} matches the signed data. * * @param expectedMessageImprintDigest * the expected message-imprint digest value * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final byte[] expectedMessageImprintDigest) { return matchData(expectedMessageImprintDigest, false); } /** * Checks if the {@code TimeStampToken} matches the signed data. * * @param expectedMessageImprintDigest * the expected message-imprint digest value * @param suppressMatchWarnings * if true the message imprint match warning * logs are suppressed. * @return true if the data is verified by the TimeStampToken */ public boolean matchData(final byte[] expectedMessageImprintDigest, final boolean suppressMatchWarnings) { processed = true; messageImprintData = expectedMessageImprintDigest != null; messageImprintIntact = false; if (messageImprintData) { Digest currentMessageImprint = getMessageImprint(); messageImprintIntact = Arrays.equals(expectedMessageImprintDigest, currentMessageImprint.getValue()); if (!messageImprintIntact && !suppressMatchWarnings) { LOG.warn("Provided digest value for TimestampToken matchData : {}", Utils.toBase64(expectedMessageImprintDigest)); LOG.warn("Digest ({}) present in TimestampToken : {}", currentMessageImprint.getAlgorithm(), Utils.toBase64(currentMessageImprint.getValue())); LOG.warn("Digest in TimestampToken matches digest of extracted data from document: {}", messageImprintIntact); } } else { LOG.warn("Timestamped data not found !"); } return messageImprintIntact; } /** * Checks if the timestamp's signature has been validated * * @return TRUE if the timestamp's signature has been validated, FALSE otherwise */ public boolean isProcessed() { return processed; } /** * Retrieves the type of the timestamp token. * * @return {@code TimestampType} */ public TimestampType getTimeStampType() { return timeStampType; } /** * Retrieves the timestamp generation time. * * @return {@code Date} */ public Date getGenerationTime() { return timeStamp.getTimeStampInfo().getGenTime(); } @Override public Date getCreationDate() { return getGenerationTime(); } /** * This method returns the embedded message-imprint value * * @return a Digest DTO with the algorithm and the value */ public Digest getMessageImprint() { if (messageImprint == null) { DigestAlgorithm messageImprintDigestAlgo = getDigestAlgorithm(); byte[] messageImprintDigestValue = timeStamp.getTimeStampInfo().getMessageImprintDigest(); messageImprint = new Digest(messageImprintDigestAlgo, messageImprintDigestValue); } return messageImprint; } /** * This method returns a {@code DigestAlgorithm} used for message-imprint computation of the timestamp token * * @return {@link DigestAlgorithm} */ public DigestAlgorithm getDigestAlgorithm() { ASN1ObjectIdentifier oid = timeStamp.getTimeStampInfo().getMessageImprintAlgOID(); return DigestAlgorithm.forOID(oid.getId()); } /** * Checks if the data for message-imprint computation has been found * * @return true if the message imprint data was found, false otherwise */ public boolean isMessageImprintDataFound() { return Utils.isTrue(messageImprintData); } /** * The method {@code matchData} must be invoked previously. * * @return true if the message imprint data is intact, false otherwise */ public boolean isMessageImprintDataIntact() { if (!processed) { throw new IllegalStateException("Invoke matchData(byte[] data) method before!"); } return Utils.isTrue(messageImprintIntact); } /** * This method returns the file name of a detached timestamp * * @return {@link String} * @deprecated since DSS 6.2. Please use {@code #getFilename} method instead. */ @Deprecated public String getFileName() { return getFilename(); } /** * Sets the filename of a detached timestamp * * @param filename * {@link String} * @deprecated since DSS 6.2. Please use {@code #setFilename} method instead. */ @Deprecated public void setFileName(String filename) { setFilename(filename); } /** * This method returns the file name of a detached timestamp * * @return {@link String} */ public String getFilename() { return filename; } /** * Sets the filename of a detached timestamp * * @param filename * {@link String} */ public void setFilename(String filename) { this.filename = filename; } /** * This method returns the covered manifest file * NOTE: applicable only for ASiC-E CAdES * * @return {@link ManifestFile} */ public ManifestFile getManifestFile() { return manifestFile; } /** * Sets the manifest file covered by the current timestamp * NOTE: applicable only for ASiC-E CAdES * * @param manifestFile * {@link ManifestFile} */ public void setManifestFile(ManifestFile manifestFile) { this.manifestFile = manifestFile; } /** * Gets list of {@code TimestampedReference}s covered by the current timestamp * * @return {@code List} of {@code TimestampReference}s */ public List getTimestampedReferences() { return timestampedReferences; } /** * Gets the {@code ArchiveTimestampType}, when applicable * * @return {@code ArchiveTimestampType} in the case of an archive timestamp, {@code null} otherwise */ public ArchiveTimestampType getArchiveTimestampType() { return archiveTimestampType; } /** * Archive timestamps can be of different subtype. * * @param archiveTimestampType * {@code ArchiveTimestampType} */ public void setArchiveTimestampType(final ArchiveTimestampType archiveTimestampType) { this.archiveTimestampType = archiveTimestampType; } /** * Gets the {@code EvidenceRecordTimestampType}, when applicable * * @return {@code EvidenceRecordTimestampType} in the case of an evidence record archive time-stamp, null otherwise */ public EvidenceRecordTimestampType getEvidenceRecordTimestampType() { return evidenceRecordTimestampType; } /** * Sets the {@code EvidenceRecordTimestampType}, for an evidence record's time-stamp * * @param evidenceRecordTimestampType {@link EvidenceRecordTimestampType} */ public void setEvidenceRecordTimestampType(EvidenceRecordTimestampType evidenceRecordTimestampType) { this.evidenceRecordTimestampType = evidenceRecordTimestampType; } /** * Applies only from XAdES timestamps * * @return {@code String} representing the canonicalization method used by the timestamp */ public String getCanonicalizationMethod() { return canonicalizationMethod; } /** * Allows to set the canonicalization method used by the timestamp. Applies only with XAdES timestamps. * * @param canonicalizationMethod * {@code String} representing the canonicalization method */ public void setCanonicalizationMethod(final String canonicalizationMethod) { this.canonicalizationMethod = canonicalizationMethod; } @Override public byte[] getEncoded() { return DSSASN1Utils.getDEREncoded(timeStamp); } /** * Returns the covered references by the current timestamp (XAdES IndividualDataObjectsTimeStamp) * * @return a list of timestamp's includes */ public List getTimestampIncludes() { return timestampIncludes; } /** * Sets the covered references by the current timestamp (XAdES IndividualDataObjectsTimeStamp) * * @param timestampIncludes a list of timestamp's includes */ public void setTimestampIncludes(List timestampIncludes) { this.timestampIncludes = timestampIncludes; } /** * Returns a list of timestamped data reference validations (used for Evidence Record timestamps) * * @return a list of {@link ReferenceValidation}s */ public List getReferenceValidations() { return referenceValidations; } /** * Sets a list of timestamped data reference validations (used for Evidence Record timestamps) * * @param referenceValidations a list of {@link ReferenceValidation}s */ public void setReferenceValidations(List referenceValidations) { this.referenceValidations = referenceValidations; } /** * This method verifies whether the corresponding reference validations are valid * * @return TRUE if all reference validations are valid, FALSE otherwise */ protected boolean areReferenceValidationsValid() { if (Utils.isCollectionNotEmpty(referenceValidations)) { for (ReferenceValidation referenceValidation : referenceValidations) { if (DigestMatcherType.EVIDENCE_RECORD_ORPHAN_REFERENCE != referenceValidation.getType() && (!referenceValidation.isFound() || !referenceValidation.isIntact())) { return false; } } } return true; } /** * Gets a list of detached evidence records covering the time-stamp, when applicable * * @return a list of {@link EvidenceRecord}s */ public List getDetachedEvidenceRecords() { if (detachedEvidenceRecords == null) { detachedEvidenceRecords = new ArrayList<>(); } return detachedEvidenceRecords; } /** * Adds an evidence record to the time-stamp's list * * @param evidenceRecord {@link EvidenceRecord} */ public void addDetachedEvidenceRecord(EvidenceRecord evidenceRecord) { getDetachedEvidenceRecords().add(evidenceRecord); } /** * Returns the scope of the current timestamp (detached timestamps only) * * @return a list of SignatureScope */ public List getTimestampScopes() { return timestampScopes; } /** * Sets timestamp's signature scopes * * @param timestampScopes a list of {@link SignatureScope}s */ public void setTimestampScopes(List timestampScopes) { this.timestampScopes = timestampScopes; } /** * Returns the list of wrapped certificates. * * @return {@code List} of {@code CertificateToken} */ public List getCertificates() { return certificateSource.getCertificates(); } /** * Returns the Set of contained certificate references. * * @return {@code Set} of {@code CertificateRef} */ public Set getCertificateRefs() { return certificateSource.getAllCertificateRefs(); } /** * Gets unsigned attribute table * * @return {@link AttributeTable} */ public AttributeTable getUnsignedAttributes() { return timeStamp.getUnsignedAttributes(); } /** * Returns a TSTInfo.tsa attribute identifying the timestamp issuer, when attribute is present * * @return {@link GeneralName} */ public X500Principal getTSTInfoTsa() { GeneralName tsaGeneralName = timeStamp.getTimeStampInfo().getTsa(); if (tsaGeneralName != null) { try { X500Name x500Name = X500Name.getInstance(tsaGeneralName.getName()); return new X500Principal(x500Name.getEncoded()); } catch (IOException e) { LOG.warn("Unable to decode TSTInfo.tsa attribute value to X500Principal. Reason : {}", e.getMessage(), e); } } return null; } /** * Gets BouncyCastle implementation of a TimestampToken * * @return {@link TimeStampToken} */ public TimeStampToken getTimeStamp() { return timeStamp; } @Override public String toString(String indentStr) { try { final StringBuilder out = new StringBuilder(); out.append(indentStr).append("TimestampToken[signedBy=").append(getIssuerX500Principal()); out.append(", generated: ").append(DSSUtils.formatDateToRFC(timeStamp.getTimeStampInfo().getGenTime())); out.append(" / ").append(timeStampType).append('\n'); if (isSignatureIntact()) { indentStr += "\t"; out.append(indentStr).append("Timestamp's signature validity: VALID").append('\n'); indentStr = indentStr.substring(1); } else { if (!signatureInvalidityReason.isEmpty()) { indentStr += "\t"; out.append(indentStr).append("Timestamp's signature validity: INVALID").append(" - ").append(signatureInvalidityReason).append('\n'); indentStr = indentStr.substring(1); } } indentStr += "\t"; if (messageImprintIntact != null) { if (Boolean.TRUE.equals(messageImprintIntact)) { out.append(indentStr).append("Timestamp MATCHES the signed data.").append('\n'); } else { out.append(indentStr).append("Timestamp DOES NOT MATCH the signed data.").append('\n'); } } out.append(']'); return out.toString(); } catch (Exception e) { return getClass().getName(); } } /** * Returns a set of found CertificateIdentifier in the SignerInformationStore * * @return a set of {@link SignerIdentifier}s */ public Set getSignerInformationStoreInfos() { return getCertificateSource().getAllCertificateIdentifiers(); } /** * Returns an object with signing candidates * * @return {@link CandidatesForSigningCertificate} */ public CandidatesForSigningCertificate getCandidatesForSigningCertificate() { if (candidatesForSigningCertificate == null) { candidatesForSigningCertificate = getCertificateSource() .getCandidatesForSigningCertificate(null); } return candidatesForSigningCertificate; } /** * Returns used signer information from CMS Signed Data object * * @return {@link SignerInformation} */ public SignerInformation getSignerInformation() { Collection signers = timeStamp.toCMSSignedData().getSignerInfos().getSigners(timeStamp.getSID()); return signers.iterator().next(); } /** * Gets the validation status of the ats-hash-index(-v3) attribute, when applicable. * NOTE: supports only archive-time-stamp-v3 timestamp type * * @return {@link ArchiveTimestampHashIndexStatus} if validation ts-hash-index(-v3) attribute has been performed, * NULL otherwise */ public ArchiveTimestampHashIndexStatus getAtsHashIndexStatus() { return hashIndexStatus; } /** * Sets the validation status of the ats-hash-index(-v3) attribute, when applicable. * * @param hashIndexStatus {@link ArchiveTimestampHashIndexStatus} */ public void setAtsHashIndexStatus(ArchiveTimestampHashIndexStatus hashIndexStatus) { this.hashIndexStatus = hashIndexStatus; } @Override protected TokenIdentifier buildTokenIdentifier() { return getTimestampIdentifierBuilder().build(); } /** * Returns a {@code TimestampTokenIdentifierBuilder} implementation * * @return {@link TimestampIdentifierBuilder} */ protected TimestampIdentifierBuilder getTimestampIdentifierBuilder() { if (identifierBuilder == null) { identifierBuilder = new TimestampIdentifierBuilder(getEncoded()).setFilename(filename); } return identifierBuilder; } @Override public byte[] getDigest(DigestAlgorithm digestAlgorithm) { return DSSUtils.digest(digestAlgorithm, getEncoded()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy