/* * DSS - Digital Signature Services * * Copyright (C) 2013 European Commission, Directorate-General Internal Market and Services (DG MARKT), B-1049 Bruxelles/Brussel * * Developed by: 2013 ARHS Developments S.A. (rue Nicolas Bové 2B, L-1253 Luxembourg) http://www.arhs-developments.com * * This file is part of the "DSS - Digital Signature Services" project. * * "DSS - Digital Signature Services" 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. * * DSS 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 * "DSS - Digital Signature Services". If not, see <http://www.gnu.org/licenses/>. */ package eu.europa.ec.markt.dss.parameter; import java.io.Serializable; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import eu.europa.ec.markt.dss.CertificateIdentifier; import eu.europa.ec.markt.dss.DSSUtils; import eu.europa.ec.markt.dss.DigestAlgorithm; import eu.europa.ec.markt.dss.EncryptionAlgorithm; import eu.europa.ec.markt.dss.SignatureAlgorithm; import eu.europa.ec.markt.dss.exception.DSSNullException; import eu.europa.ec.markt.dss.signature.DSSDocument; import eu.europa.ec.markt.dss.signature.ProfileParameters; import eu.europa.ec.markt.dss.signature.SignatureLevel; import eu.europa.ec.markt.dss.signature.SignaturePackaging; import eu.europa.ec.markt.dss.signature.token.DSSPrivateKeyEntry; import eu.europa.ec.markt.dss.signature.token.SignatureTokenConnection; import eu.europa.ec.markt.dss.validation102853.SignatureForm; import eu.europa.ec.markt.dss.validation102853.TimestampToken; import eu.europa.ec.markt.dss.validation102853.xades.XPathQueryHolder; /** * Parameters for a Signature creation/extension * * @version $Revision: 2686 $ - $Date: 2013-10-02 14:02:33 +0200 (Wed, 02 Oct 2013) $ */ public class SignatureParameters implements Serializable { /** * This variable is used to ensure the uniqueness of the signature in the same document. */ protected static int signatureCounter = 0; /** * This parameter is used in one shot signature process. Cannot be used with 3-steps signature process. */ private SignatureTokenConnection signingToken; /** * This parameter is used in one shot signature process. Cannot be used with 3-steps signature process. */ private DSSPrivateKeyEntry privateKeyEntry; /** * This field contains the signing certificate. */ private X509Certificate signingCertificate; /** * This variable indicates if it is possible to sign with an expired certificate. */ private boolean signWithExpiredCertificate = false; /** * This field contains the {@code List} of chain of certificates. It includes the signing certificate. */ private List<ChainCertificate> certificateChain = new ArrayList<ChainCertificate>(); ProfileParameters context; private SignatureLevel signatureLevel; private SignaturePackaging signaturePackaging; /** * XAdES: ds:CanonicalizationMethod indicates the canonicalization algorithm: Algorithm="..." for SignedInfo. */ private String signedInfoCanonicalizationMethod; /** * XAdES: ds:CanonicalizationMethod indicates the canonicalization algorithm: Algorithm="..." for SignedProperties. */ private String signedPropertiesCanonicalizationMethod; /** * XAdES: The ds:SignatureMethod indicates the algorithms used to sign ds:SignedInfo. */ private SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA256; /** * The encryption algorithm shall be automatically extracted from the signing token. */ private EncryptionAlgorithm encryptionAlgorithm = signatureAlgorithm.getEncryptionAlgorithm(); /** * XAdES: The digest algorithm used to hash ds:SignedInfo. */ private DigestAlgorithm digestAlgorithm = signatureAlgorithm.getDigestAlgorithm(); private List<DSSReference> dssReferences; /** * The object representing the parameters related to B- level. */ private BLevelParameters bLevelParams = new BLevelParameters(); /** * The object representing the parameters related to ASiC from of the signature. */ private ASiCParameters aSiCParams = new ASiCParameters(); private String reason; private String contactInfo; private String deterministicId; private String toCounterSignSignatureId; private String xPathLocationString; private TimestampParameters signatureTimestampParameters; private TimestampParameters archiveTimestampParameters; private TimestampParameters contentTimestampParameters; private List<TimestampToken> contentTimestamps; private XPathQueryHolder toCountersignXPathQueryHolder = new XPathQueryHolder(); private String toCounterSignSignatureValueId; public SignatureParameters() { } /** * The document to be signed */ private DSSDocument detachedContent; // TODO-Bob (11/09/2014): More then one document // /** // * The documents to be signed. In the case where more then one document should be signed. // */ // private List<DSSDocument> detachedContents; /** * Copy constructor (used by ASiC) */ public SignatureParameters(final SignatureParameters source) { if (source == null) { throw new DSSNullException(SignatureParameters.class); } bLevelParams = new BLevelParameters(source.bLevelParams); aSiCParams = new ASiCParameters(source.aSiCParams); certificateChain = new ArrayList<ChainCertificate>(source.certificateChain); contactInfo = source.contactInfo; deterministicId = source.getDeterministicId(); digestAlgorithm = source.digestAlgorithm; encryptionAlgorithm = source.encryptionAlgorithm; detachedContent = source.detachedContent; privateKeyEntry = source.privateKeyEntry; reason = source.reason; signedInfoCanonicalizationMethod = source.signedInfoCanonicalizationMethod; signedPropertiesCanonicalizationMethod = source.signedPropertiesCanonicalizationMethod; signatureAlgorithm = source.signatureAlgorithm; signaturePackaging = source.signaturePackaging; signatureLevel = source.signatureLevel; signingToken = source.signingToken; signingCertificate = source.signingCertificate; signWithExpiredCertificate = source.signWithExpiredCertificate; contentTimestamps = source.getContentTimestamps(); toCounterSignSignatureId = source.getToCounterSignSignatureId(); signatureTimestampParameters = source.signatureTimestampParameters; archiveTimestampParameters = source.archiveTimestampParameters; toCountersignXPathQueryHolder = source.toCountersignXPathQueryHolder; final List<DSSReference> references = source.getReferences(); if (references != null && references.size() > 0) { dssReferences = new ArrayList<DSSReference>(); for (final DSSReference reference : references) { final DSSReference dssReference = new DSSReference(reference); dssReferences.add(dssReference); } } // This is a simple copy of reference and not of the object content! context = source.context; } /** * This method returns the Id of the signature to be countersigned. * * @return */ public String getToCounterSignSignatureId() { return toCounterSignSignatureId; } /** * This method sets the Id of the signature to be countersigned. * * @param toCounterSignSignatureId */ public void setToCounterSignSignatureId(String toCounterSignSignatureId) { this.toCounterSignSignatureId = toCounterSignSignatureId; } /** * This method returns the document to sign. In the case of the DETACHED signature this is the detached document. * * @return * @deprecated (4.1.0) use {@code getContents} */ @Deprecated public DSSDocument getOriginalDocument() { return detachedContent; } /** * This method returns the document to sign. In the case of the DETACHED signature this is the detached document. * * @return */ public DSSDocument getDetachedContent() { return detachedContent; } /** * When signing this method is internally invoked by the {@code AbstractSignatureService} and the related variable {@code detachedContent} is overwritten by the service * parameter. In the case of the DETACHED signature this is the detached document. In the case of ASiC-S this is the document to be signed.<p /> * When extending this method must be invoked to indicate the {@code detachedContent}. * * @param document * @deprecated (4.1.0) use {@code setContents} */ @Deprecated public void setOriginalDocument(final DSSDocument document) { this.detachedContent = document; } /** * When signing this method is internally invoked by the {@code AbstractSignatureService} and the related variable {@code detachedContent} is overwritten by the service * parameter. In the case of the DETACHED signature this is the detached document. In the case of ASiC-S this is the document to be signed.<p /> * When extending this method must be invoked to indicate the {@code detachedContent}. * * @param detachedContent */ public void setDetachedContent(final DSSDocument detachedContent) { this.detachedContent = detachedContent; } /** * Returns the list of the {@code TimestampToken} to be incorporated within the signature and representing the content-timestamp. * * @return {@code List} of {@code TimestampToken} */ public List<TimestampToken> getContentTimestamps() { return contentTimestamps; } public void setContentTimestamps(final List<TimestampToken> contentTimestamps) { this.contentTimestamps = contentTimestamps; } public void addContentTimestamp(final TimestampToken contentTimestamp) { if (contentTimestamps == null) { contentTimestamps = new ArrayList<TimestampToken>(); } this.contentTimestamps.add(contentTimestamp); } /** * XAdES: The ID of xades:SignedProperties is contained in the signed content of the xades Signature. We must create this ID in a deterministic way. * * @return */ public String getDeterministicId() { if (deterministicId != null) { return deterministicId; } final int dssId = (signingCertificate == null ? 0 : CertificateIdentifier.getId(signingCertificate)) + signatureCounter++; deterministicId = DSSUtils.getDeterministicId(bLevelParams.getSigningDate(), dssId); return deterministicId; } /** * This method allows to set the XAdES signature id. Be careful, if you change this id between the call to eu.europa.ec.markt.dss.signature.xades.XAdESService#toBeSigned(eu * .europa.ec.markt.dss.signature.DSSDocument, eu.europa.ec.markt.dss.parameter.SignatureParameters) and eu.europa.ec.markt.dss.signature.xades.XAdESService#signDocument(eu * .europa.ec.markt.dss.signature.DSSDocument, eu.europa.ec.markt.dss.parameter.SignatureParameters, byte[]) the created signature will be corrupted. * * @param deterministicId */ public void setDeterministicId(final String deterministicId) { this.deterministicId = deterministicId; } public ProfileParameters getContext() { if (context == null) { context = new ProfileParameters(); } return context; } /** * Get the signing certificate * * @return the value */ public X509Certificate getSigningCertificate() { return signingCertificate; } /** * Set the signing certificate. If this certificate is not a part of the certificate chain then it's added as the first one of the chain. * * @param signingCertificate the value */ public void setSigningCertificate(final X509Certificate signingCertificate) { this.signingCertificate = signingCertificate; final ChainCertificate chainCertificate = new ChainCertificate(signingCertificate, true); if (!this.certificateChain.contains(chainCertificate)) { this.certificateChain.add(0, chainCertificate); } } /** * Indicates if it is possible to sign with an expired certificate. The default value is false. * * @return */ public boolean isSignWithExpiredCertificate() { return signWithExpiredCertificate; } /** * Allows to change the default behaviour regarding the use of an expired certificate. * * @param signWithExpiredCertificate */ public void setSignWithExpiredCertificate(final boolean signWithExpiredCertificate) { this.signWithExpiredCertificate = signWithExpiredCertificate; } /** * Set the certificate chain * * @return the value */ public List<ChainCertificate> getCertificateChain() { return certificateChain; } /** * Clears the certificate chain * * @return the value */ public void clearCertificateChain() { certificateChain.clear(); } /** * Set the certificate chain * * @param certificateChain the {@code List} of {@code ChainCertificate}s */ public void setCertificateChain(final List<ChainCertificate> certificateChain) { if (certificateChain != null) { this.certificateChain = certificateChain; } else { this.certificateChain.clear(); } } /** * This method sets the list of certificates which constitute the chain. If the certificate is already present in the array then it is ignored. * * @param certificateChainArray the array containing all certificates composing the chain */ public void setCertificateChain(final X509Certificate... certificateChainArray) { if (certificateChainArray == null || certificateChainArray.length == 0) { certificateChain.clear(); } for (final X509Certificate certificate : certificateChainArray) { if (certificate != null) { final ChainCertificate chainCertificate = new ChainCertificate(certificate, false); if (!certificateChain.contains(chainCertificate)) { certificateChain.add(chainCertificate); } } } } /** * This method sets the private key entry used to create the signature. Note that the certificate chain is reset, the encryption algorithm is set and the signature algorithm * is updated. * * @param privateKeyEntry the private key entry used to sign? */ public void setPrivateKeyEntry(final DSSPrivateKeyEntry privateKeyEntry) { this.privateKeyEntry = privateKeyEntry; // When the private key entry is set the certificate chain is reset certificateChain.clear(); setSigningCertificate(privateKeyEntry.getCertificate()); setCertificateChain(privateKeyEntry.getCertificateChain()); final String encryptionAlgorithmName = this.signingCertificate.getPublicKey().getAlgorithm(); this.encryptionAlgorithm = EncryptionAlgorithm.forName(encryptionAlgorithmName); this.signatureAlgorithm = SignatureAlgorithm.getAlgorithm(this.encryptionAlgorithm, this.digestAlgorithm); } /** * Returns the private key entry * * @return the value */ public DSSPrivateKeyEntry getPrivateKeyEntry() { return privateKeyEntry; } /** * Returns the connection through available API to the SSCD (SmartCard, MSCAPI, PKCS#12) * * @return the value */ public SignatureTokenConnection getSigningToken() { return signingToken; } /** * Sets the connection through available API to the SSCD (SmartCard, MSCAPI, PKCS#12) * * @param signingToken the value */ public void setSigningToken(final SignatureTokenConnection signingToken) { this.signingToken = signingToken; } /** * Get signature format: XAdES_BES, XAdES_EPES, XAdES_BASELINE_T ../.. CAdES_BES... * * @return the value */ public SignatureLevel getSignatureLevel() { return signatureLevel; } /** * Set signature level. This field cannot be null. * * @param signatureLevel the value */ public void setSignatureLevel(final SignatureLevel signatureLevel) throws DSSNullException { if (signatureLevel == null) { throw new DSSNullException(SignatureLevel.class); } final SignatureForm signatureForm = signatureLevel.getSignatureForm(); if (SignatureForm.ASiC_S.equals(signatureForm) || SignatureForm.ASiC_E.equals(signatureForm)) { aSiC().containerForm = signatureForm; } this.signatureLevel = signatureLevel; } /** * Get Signature packaging * * @return the value */ public SignaturePackaging getSignaturePackaging() { return signaturePackaging; } /** * Set Signature packaging * * @param signaturePackaging the value */ public void setSignaturePackaging(final SignaturePackaging signaturePackaging) { this.signaturePackaging = signaturePackaging; } /** * @return (XAdES) the canonicalization algorithm to be used when dealing with SignedInfo. */ public String getSignedInfoCanonicalizationMethod() { return signedInfoCanonicalizationMethod; } /** * Set the canonicalization algorithm to be used when dealing with SignedInfo (XAdES). * * @param signedInfoCanonicalizationMethod the canonicalization algorithm to be used when dealing with SignedInfo. */ public void setSignedInfoCanonicalizationMethod(final String signedInfoCanonicalizationMethod) { this.signedInfoCanonicalizationMethod = signedInfoCanonicalizationMethod; } /** * @return (XAdES) the canonicalization algorithm to be used when dealing with SignedProperties. */ public String getSignedPropertiesCanonicalizationMethod() { return signedPropertiesCanonicalizationMethod; } /** * Set the canonicalization algorithm to be used when dealing with SignedProperties (XAdES). * * @param signedPropertiesCanonicalizationMethod the canonicalization algorithm to be used when dealing with SignedInfo. */ public void setSignedPropertiesCanonicalizationMethod(final String signedPropertiesCanonicalizationMethod) { this.signedPropertiesCanonicalizationMethod = signedPropertiesCanonicalizationMethod; } /** * @return the digest algorithm */ public DigestAlgorithm getDigestAlgorithm() { return digestAlgorithm; } /** * @param digestAlgorithm the digest algorithm to set */ public void setDigestAlgorithm(final DigestAlgorithm digestAlgorithm) { this.digestAlgorithm = digestAlgorithm; if (this.digestAlgorithm != null && this.encryptionAlgorithm != null) { signatureAlgorithm = SignatureAlgorithm.getAlgorithm(this.encryptionAlgorithm, this.digestAlgorithm); } } /** * This setter should be used only when dealing with web services (or when signing in three steps). Usually the encryption algorithm is automatically extrapolated from the * private key. * * @param encryptionAlgorithm */ public void setEncryptionAlgorithm(final EncryptionAlgorithm encryptionAlgorithm) { this.encryptionAlgorithm = encryptionAlgorithm; if (this.digestAlgorithm != null && this.encryptionAlgorithm != null) { signatureAlgorithm = SignatureAlgorithm.getAlgorithm(this.encryptionAlgorithm, this.digestAlgorithm); } } /** * @return the encryption algorithm. It's determined by the privateKeyEntry and is null until the privateKeyEntry is set. */ public EncryptionAlgorithm getEncryptionAlgorithm() { return encryptionAlgorithm; } /** * Gets the signature algorithm. * * @return the value */ public SignatureAlgorithm getSignatureAlgorithm() { return signatureAlgorithm; } public List<DSSReference> getReferences() { return dssReferences; } public void setReferences(List<DSSReference> references) { this.dssReferences = references; } /** * @return the reason (used by PAdES) */ public String getReason() { return reason; } /** * @param reason the reason to set (used by PAdES) */ public void setReason(final String reason) { this.reason = reason; } /** * @return the contactInfo (used by PAdES) */ public String getContactInfo() { return contactInfo; } /** * @param contactInfo the contactInfo to set (used by PAdES) */ public void setContactInfo(final String contactInfo) { this.contactInfo = contactInfo; } public BLevelParameters bLevel() { return bLevelParams; } public ASiCParameters aSiC() { if (aSiCParams == null) { aSiCParams = new ASiCParameters(); } return aSiCParams; } public TimestampParameters getSignatureTimestampParameters() { if (signatureTimestampParameters == null) { signatureTimestampParameters = new TimestampParameters(); } return signatureTimestampParameters; } public void setSignatureTimestampParameters(TimestampParameters signatureTimestampParameters) { this.signatureTimestampParameters = signatureTimestampParameters; } public TimestampParameters getArchiveTimestampParameters() { if (archiveTimestampParameters == null) { archiveTimestampParameters = new TimestampParameters(); } return archiveTimestampParameters; } public void setArchiveTimestampParameters(TimestampParameters archiveTimestampParameters) { this.archiveTimestampParameters = archiveTimestampParameters; } public TimestampParameters getContentTimestampParameters() { if (contentTimestampParameters == null) { contentTimestampParameters = new TimestampParameters(); } return contentTimestampParameters; } public void setContentTimestampParameters(TimestampParameters contentTimestampParameters) { this.contentTimestampParameters = contentTimestampParameters; } public String getXPathLocationString() { return xPathLocationString; } public void setXPathLocationString(String xPathLocationString) { this.xPathLocationString = xPathLocationString; } public XPathQueryHolder getToCountersignXPathQueryHolder() { return toCountersignXPathQueryHolder; } public void setToCountersignXPathQueryHolder(XPathQueryHolder toCountersignXPathQueryHolder) { this.toCountersignXPathQueryHolder = toCountersignXPathQueryHolder; } public String getToCounterSignSignatureValueId() { return toCounterSignSignatureValueId; } public void setToCounterSignSignatureValueId(String toCounterSignSignatureValueId) { this.toCounterSignSignatureValueId = toCounterSignSignatureValueId; } @Override public String toString() { return "SignatureParameters{" + "signingToken=" + signingToken + ", privateKeyEntry=" + privateKeyEntry + ", signingCertificate=" + signingCertificate + ", signWithExpiredCertificate=" + signWithExpiredCertificate + ", certificateChain_=" + certificateChain + ", context=" + context + ", signatureLevel=" + signatureLevel + ", signaturePackaging=" + signaturePackaging + ", signatureAlgorithm=" + signatureAlgorithm + ", encryptionAlgorithm=" + encryptionAlgorithm + ", digestAlgorithm=" + digestAlgorithm + ", references=" + dssReferences + ", bLevelParams=" + bLevelParams + ", aSiCParams=" + aSiCParams + ", reason='" + reason + '\'' + ", contactInfo='" + contactInfo + '\'' + ", deterministicId='" + deterministicId + '\'' + ", signatureTimestampParameters=" + signatureTimestampParameters.toString() + ", archiveTimestampParameters=" + archiveTimestampParameters.toString() + ", contentTimestamps=" + contentTimestamps + ", detachedContent=" + detachedContent + ", toCountersignSignatureId=" + toCounterSignSignatureId + ", toCountersignXPathQueryHolder=" + toCountersignXPathQueryHolder.toString() + '}'; } }