eu.europa.esig.dss.validation.DefaultAdvancedSignature Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dss-document Show documentation
Show all versions of dss-document Show documentation
DSS Document contains the code for the creation and validation of XAdES, CAdES, PAdES and ASiC signatures.
/**
* 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.validation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import eu.europa.esig.dss.model.DSSDocument;
import eu.europa.esig.dss.model.DSSException;
import eu.europa.esig.dss.model.DigestDocument;
import eu.europa.esig.dss.model.x509.CertificateToken;
import eu.europa.esig.dss.spi.x509.CandidatesForSigningCertificate;
import eu.europa.esig.dss.spi.x509.CertificateIdentifier;
import eu.europa.esig.dss.spi.x509.CertificateValidity;
import eu.europa.esig.dss.spi.x509.ListCertificateSource;
import eu.europa.esig.dss.spi.x509.revocation.crl.OfflineCRLSource;
import eu.europa.esig.dss.spi.x509.revocation.ocsp.OfflineOCSPSource;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.validation.scope.SignatureScope;
import eu.europa.esig.dss.validation.scope.SignatureScopeFinder;
import eu.europa.esig.dss.validation.timestamp.TimestampSource;
import eu.europa.esig.dss.validation.timestamp.TimestampToken;
public abstract class DefaultAdvancedSignature implements AdvancedSignature {
private static final long serialVersionUID = 6452189007886779360L;
/**
* In the case of a non AdES signature the signing certificate is not mandatory within the signature and can be provided by the driving application.
*/
protected CertificateToken providedSigningCertificateToken;
/**
* In case of a detached signature this is the signed document.
*/
protected List detachedContents;
/**
* In case of a ASiC signature this is the archive or manifest content.
*/
private List containerContents;
/**
* In case of a ASiC-E signature this is the list of found manifest files.
*/
protected List manifestFiles;
/**
* This variable contains a list of reference validations (reference tag for
* XAdES or message-digest for CAdES)
*/
protected List referenceValidations;
/**
* This variable contains the result of the signature mathematical validation. It is initialised when the method
* {@code checkSignatureIntegrity} is called.
*/
protected SignatureCryptographicVerification signatureCryptographicVerification;
protected String structureValidation;
private CertificateVerifier offlineCertificateVerifier;
// Cached {@code SignatureCertificateSource}
protected SignatureCertificateSource offlineCertificateSource;
// Cached {@code OfflineCRLSource}
protected OfflineCRLSource signatureCRLSource;
// Cached {@code OfflineOCSPSource}
protected OfflineOCSPSource signatureOCSPSource;
// Cached {@code TimestampSource}
protected TimestampSource signatureTimestampSource;
private AdvancedSignature masterSignature;
protected SignaturePolicy signaturePolicy;
private List signatureScopes;
private String signatureFilename;
/*
* Unique signature identifier
*/
protected SignatureIdentifier signatureIdentifier;
/**
* Build and defines {@code signatureIdentifier} value
*/
protected abstract SignatureIdentifier buildSignatureIdentifier();
@Override
public String getSignatureFilename() {
return signatureFilename;
}
@Override
public void setSignatureFilename(String signatureFilename) {
this.signatureFilename = signatureFilename;
}
@Override
public List getDetachedContents() {
return detachedContents;
}
@Override
public void setDetachedContents(final List detachedContents) {
this.detachedContents = detachedContents;
}
@Override
public List getContainerContents() {
return containerContents;
}
@Override
public void setContainerContents(List containerContents) {
this.containerContents = containerContents;
}
@Override
public void setManifestFiles(List manifestFiles) {
this.manifestFiles = manifestFiles;
}
@Override
public SignatureIdentifier getDSSId() {
if (signatureIdentifier == null) {
signatureIdentifier = buildSignatureIdentifier();
}
return signatureIdentifier;
}
@Override
public String getId() {
return getDSSId().asXmlId();
}
@Override
public List getManifestedDocuments() {
if (Utils.isCollectionEmpty(manifestFiles) || Utils.isCollectionEmpty(containerContents)) {
return Collections.emptyList();
}
List foundManifestedDocuments = new ArrayList<>();
for (ManifestFile manifestFile : manifestFiles) {
if (Utils.areStringsEqual(manifestFile.getSignatureFilename(), signatureFilename)) {
for (DSSDocument document : containerContents) {
for (ManifestEntry entry : manifestFile.getEntries()) {
if (Utils.areStringsEqual(entry.getFileName(), document.getName())) {
foundManifestedDocuments.add(document);
}
}
}
break;
}
}
return foundManifestedDocuments;
}
@Override
public ListCertificateSource getCompleteCertificateSource() {
ListCertificateSource certificateSource = new ListCertificateSource(getCertificateSource());
certificateSource.addAll(getTimestampSource().getTimestampCertificateSources());
return certificateSource;
}
public ListCertificateSource getCertificateSourcesExceptLastArchiveTimestamp() {
ListCertificateSource certificateSource = new ListCertificateSource(getCertificateSource());
certificateSource.addAll(getTimestampSource().getTimestampCertificateSourcesExceptLastArchiveTimestamp());
return certificateSource;
}
@Override
public ListRevocationSource getCompleteCRLSource() {
ListRevocationSource crlSource = new ListRevocationSource(getCRLSource());
crlSource.addAll(getTimestampSource().getTimestampCRLSources());
return crlSource;
}
@Override
public ListRevocationSource getCompleteOCSPSource() {
ListRevocationSource ocspSource = new ListRevocationSource(getOCSPSource());
ocspSource.addAll(getTimestampSource().getTimestampOCSPSources());
return ocspSource;
}
/**
* ETSI TS 101 733 V2.2.1 (2013-04)
* 5.6.3 Signature Verification Process
* ...the public key from the first certificate identified in the sequence
* of certificate identifiers from SigningCertificate shall be the key used
* to verify the digital signature.
*
* @return
*/
@Override
public CandidatesForSigningCertificate getCandidatesForSigningCertificate() {
return getCertificateSource().getCandidatesForSigningCertificate(providedSigningCertificateToken);
}
/**
* This method prepares an offline CertificateVerifier. The instance is used to
* know if all required revocation data are present
*
* @param certificateVerifier the configured CertificateVerifier with all
* external sources
*/
public void prepareOfflineCertificateVerifier(final CertificateVerifier certificateVerifier) {
offlineCertificateVerifier = new CertificateVerifierBuilder(certificateVerifier).buildOfflineAndSilentCopy();
}
/**
* This method validates the signing certificate and all timestamps.
*
* @return signature validation context containing all certificates and
* revocation data used during the validation process.
*/
public ValidationContext getSignatureValidationContext(final CertificateVerifier certificateVerifier) {
final ValidationContext validationContext = new SignatureValidationContext();
certificateVerifier.setSignatureCRLSource(getCompleteCRLSource());
certificateVerifier.setSignatureOCSPSource(getCompleteOCSPSource());
certificateVerifier.setSignatureCertificateSource(getCompleteCertificateSource());
validationContext.initialize(certificateVerifier);
if (providedSigningCertificateToken != null) {
validationContext.addCertificateTokenForVerification(providedSigningCertificateToken);
}
final List certificates = getCertificates();
for (final CertificateToken certificate : certificates) {
validationContext.addCertificateTokenForVerification(certificate);
}
prepareTimestamps(validationContext);
validationContext.validate();
validationContext.checkAllTimestampsValid();
validationContext.checkAllRequiredRevocationDataPresent();
validationContext.checkAllPOECoveredByRevocationData();
validationContext.checkAllCertificatesValid();
CertificateToken signingCertificateToken = getSigningCertificateToken();
validationContext.checkAtLeastOneRevocationDataPresentAfterBestSignatureTime(signingCertificateToken);
return validationContext;
}
/**
* Returns an unmodifiable list of all certificate tokens encapsulated in the
* signature
*
* @see eu.europa.esig.dss.validation.AdvancedSignature#getCertificates()
*/
@Override
public List getCertificates() {
return getCertificateSource().getCertificates();
}
@Override
public void setMasterSignature(final AdvancedSignature masterSignature) {
this.masterSignature = masterSignature;
}
@Override
public AdvancedSignature getMasterSignature() {
return masterSignature;
}
@Override
public boolean isCounterSignature() {
return masterSignature != null;
}
@Override
public SignatureCryptographicVerification getSignatureCryptographicVerification() {
if (signatureCryptographicVerification == null) {
checkSignatureIntegrity();
}
return signatureCryptographicVerification;
}
@Override
public List getSignerRoles() {
List signerRoles = new ArrayList<>();
List claimedSignerRoles = getClaimedSignerRoles();
if (Utils.isCollectionNotEmpty(claimedSignerRoles)) {
signerRoles.addAll(claimedSignerRoles);
}
List certifiedSignerRoles = getCertifiedSignerRoles();
if (Utils.isCollectionNotEmpty(certifiedSignerRoles)) {
signerRoles.addAll(certifiedSignerRoles);
}
List signedAssertionSignerRoles = getSignedAssertions();
if (Utils.isCollectionNotEmpty(signedAssertionSignerRoles)) {
signerRoles.addAll(signedAssertionSignerRoles);
}
return signerRoles;
}
@Override
public CertificateToken getProvidedSigningCertificateToken() {
return providedSigningCertificateToken;
}
@Override
public void setProvidedSigningCertificateToken(final CertificateToken certificateToken) {
this.providedSigningCertificateToken = certificateToken;
}
@Override
public CertificateToken getSigningCertificateToken() {
// This ensures that the variable candidatesForSigningCertificate has been initialized
CandidatesForSigningCertificate candidatesForSigningCertificate = getCertificateSource()
.getCandidatesForSigningCertificate(providedSigningCertificateToken);
// This ensures that the variable signatureCryptographicVerification has been initialized
signatureCryptographicVerification = getSignatureCryptographicVerification();
final CertificateValidity theCertificateValidity = candidatesForSigningCertificate.getTheCertificateValidity();
if (theCertificateValidity != null) {
if (theCertificateValidity.isValid()) {
final CertificateToken signingCertificateToken = theCertificateValidity.getCertificateToken();
return signingCertificateToken;
}
}
final CertificateValidity theBestCandidate = candidatesForSigningCertificate.getTheBestCandidate();
return theBestCandidate == null ? null : theBestCandidate.getCertificateToken();
}
/**
* This method adds to the {@code ValidationContext} all timestamps to be validated.
*
* @param validationContext
* {@code ValidationContext} to which the timestamps must be added
*/
@Override
public void prepareTimestamps(final ValidationContext validationContext) {
/*
* This validates the signature timestamp tokens present in the signature.
*/
for (final TimestampToken timestampToken : getContentTimestamps()) {
validationContext.addTimestampTokenForVerification(timestampToken);
}
/*
* This validates the signature timestamp tokens present in the signature.
*/
for (final TimestampToken timestampToken : getSignatureTimestamps()) {
validationContext.addTimestampTokenForVerification(timestampToken);
}
/*
* This validates the SigAndRefs timestamp tokens present in the signature.
*/
for (final TimestampToken timestampToken : getTimestampsX1()) {
validationContext.addTimestampTokenForVerification(timestampToken);
}
/*
* This validates the RefsOnly timestamp tokens present in the signature.
*/
for (final TimestampToken timestampToken : getTimestampsX2()) {
validationContext.addTimestampTokenForVerification(timestampToken);
}
/*
* This validates the archive timestamp tokens present in the signature.
*/
for (final TimestampToken timestampToken : getArchiveTimestamps()) {
validationContext.addTimestampTokenForVerification(timestampToken);
}
}
@Override
public void validateStructure() {
}
@Override
public String getStructureValidationResult() {
return structureValidation;
}
@Override
public SignaturePolicy getPolicyId() {
return signaturePolicy;
}
@Override
public void findSignatureScope(SignatureScopeFinder signatureScopeFinder) {
signatureScopes = signatureScopeFinder.findSignatureScope(this);
}
@Override
public List getSignatureScopes() {
return signatureScopes;
}
@Override
public List getContentTimestamps() {
return getTimestampSource().getContentTimestamps();
}
@Override
public List getSignatureTimestamps() {
return getTimestampSource().getSignatureTimestamps();
}
@Override
public List getTimestampsX1() {
return getTimestampSource().getTimestampsX1();
}
@Override
public List getTimestampsX2() {
return getTimestampSource().getTimestampsX2();
}
@Override
public List getArchiveTimestamps() {
return getTimestampSource().getArchiveTimestamps();
}
@Override
public List getDocumentTimestamps() {
return getTimestampSource().getDocumentTimestamps();
}
@Override
public List getAllTimestamps() {
return getTimestampSource().getAllTimestamps();
}
@Override
public void addExternalTimestamp(TimestampToken timestamp) {
if (!timestamp.isProcessed()) {
throw new DSSException("Timestamp token must be validated first !");
}
if (!timestamp.getTimeStampType().isArchivalTimestamp()) {
throw new DSSException("Only archival timestamp is allowed !");
}
getTimestampSource().addExternalTimestamp(timestamp);
}
/* Defines the level T */
public boolean hasTProfile() {
return Utils.isCollectionNotEmpty(getSignatureTimestamps());
}
/* Defines the level LT */
public boolean hasLTProfile() {
ListCertificateSource certificateSources = getCertificateSourcesExceptLastArchiveTimestamp();
boolean certificateFound = certificateSources.getNumberOfCertificates() > 0;
boolean allSelfSigned = certificateFound && certificateSources.isAllSelfSigned();
boolean emptyCRLs = getCompleteCRLSource().getAllRevocationBinaries().isEmpty();
boolean emptyOCSPs = getCompleteOCSPSource().getAllRevocationBinaries().isEmpty();
boolean emptyRevocation = emptyCRLs && emptyOCSPs;
boolean minimalLTrequirement = !allSelfSigned && !emptyRevocation;
if (minimalLTrequirement) {
// check presence of all revocation data
return isAllRevocationDataPresent(certificateSources);
}
return minimalLTrequirement;
}
private boolean isAllRevocationDataPresent(ListCertificateSource certificateSources) {
SignatureValidationContext validationContext = new SignatureValidationContext();
offlineCertificateVerifier.setSignatureCRLSource(getCompleteCRLSource());
offlineCertificateVerifier.setSignatureOCSPSource(getCompleteOCSPSource());
offlineCertificateVerifier.setSignatureCertificateSource(getCompleteCertificateSource());
validationContext.initialize(offlineCertificateVerifier);
if (providedSigningCertificateToken != null) {
validationContext.addCertificateTokenForVerification(providedSigningCertificateToken);
}
for (final CertificateToken certificate : certificateSources.getAllCertificateTokens()) {
validationContext.addCertificateTokenForVerification(certificate);
}
validationContext.validate();
return validationContext.checkAllRequiredRevocationDataPresent();
}
@Override
public boolean areAllSelfSignedCertificates() {
ListCertificateSource certificateSources = getCompleteCertificateSource();
boolean certificateFound = certificateSources.getNumberOfCertificates() > 0;
return certificateFound && certificateSources.isAllSelfSigned();
}
/* Defines the level LTA */
public boolean hasLTAProfile() {
return Utils.isCollectionNotEmpty(getArchiveTimestamps());
}
@Override
public boolean isDocHashOnlyValidation() {
if (Utils.isCollectionNotEmpty(detachedContents)) {
for (DSSDocument dssDocument : detachedContents) {
if (!(dssDocument instanceof DigestDocument)) {
return false;
}
}
return true;
}
return false;
}
@Override
public boolean isHashOnlyValidation() {
// TODO: not implemented yet
return false;
}
@Override
public byte[] getMessageDigestValue() {
// Not applicable by default (CAdES/PAdES only)
return null;
}
@Override
public Set getSignerInformationStoreInfos() {
// Not applicable by default (CAdES/PAdES only)
return Collections.emptySet();
}
@Override
public PdfRevision getPdfRevision() {
// Not applicable by default (PDF only)
return null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if ((obj == null) || !(obj instanceof DefaultAdvancedSignature)) {
return false;
}
DefaultAdvancedSignature das = (DefaultAdvancedSignature) obj;
return getDSSId().equals(das.getDSSId());
}
@Override
public int hashCode() {
return getDSSId().hashCode();
}
@Override
public String toString() {
return String.format("%s Signature with Id : %s", getSignatureForm(), getId());
}
}