/*
* 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.ws.impl;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.jws.WebService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.exception.DSSException;
import eu.europa.ec.markt.dss.parameter.BLevelParameters;
import eu.europa.ec.markt.dss.parameter.ChainCertificate;
import eu.europa.ec.markt.dss.parameter.DSSReference;
import eu.europa.ec.markt.dss.parameter.SignatureParameters;
import eu.europa.ec.markt.dss.signature.DSSDocument;
import eu.europa.ec.markt.dss.signature.DocumentSignatureService;
import eu.europa.ec.markt.dss.signature.SignatureLevel;
import eu.europa.ec.markt.dss.signature.SignaturePackaging;
import eu.europa.ec.markt.dss.ws.DSSWSUtils;
import eu.europa.ec.markt.dss.ws.SignatureService;
import eu.europa.ec.markt.dss.ws.WSChainCertificate;
import eu.europa.ec.markt.dss.ws.WSDSSReference;
import eu.europa.ec.markt.dss.ws.WSDocument;
import eu.europa.ec.markt.dss.ws.WSParameters;
/**
* Implementation of the Interface for the Contract of the Signature Web Service.
*
* @version $Revision$ - $Date$
*/
@WebService(endpointInterface = "eu.europa.ec.markt.dss.ws.SignatureService", serviceName = "SignatureService")
public class SignatureServiceImpl implements SignatureService {
private static final Logger LOG = LoggerFactory.getLogger(SignatureServiceImpl.class);
private DocumentSignatureService xadesService;
private DocumentSignatureService cadesService;
private DocumentSignatureService padesService;
private DocumentSignatureService asicService;
/**
* @param xadesService the xadesService to set
*/
public void setXadesService(final DocumentSignatureService xadesService) {
this.xadesService = xadesService;
}
/**
* @param cadesService the cadesService to set
*/
public void setCadesService(final DocumentSignatureService cadesService) {
this.cadesService = cadesService;
}
/**
* @param padesService the padesService to set
*/
public void setPadesService(final DocumentSignatureService padesService) {
this.padesService = padesService;
}
/**
* @param asicService the asicService to set
*/
public void setAsicService(final DocumentSignatureService asicService) {
this.asicService = asicService;
}
private DocumentSignatureService getServiceForSignatureLevel(final SignatureLevel signatureLevel) {
switch (signatureLevel) {
case XAdES_BASELINE_B:
case XAdES_BASELINE_T:
case XAdES_C:
case XAdES_X:
case XAdES_XL:
case XAdES_BASELINE_LT:
case XAdES_A:
case XAdES_BASELINE_LTA:
return xadesService;
case CAdES_BASELINE_B:
case CAdES_BASELINE_T:
case CAdES_BASELINE_LT:
case CAdES_BASELINE_LTA:
return cadesService;
case PAdES_BASELINE_B:
case PAdES_BASELINE_T:
case PAdES_BASELINE_LT:
case PAdES_BASELINE_LTA:
return padesService;
case ASiC_S_BASELINE_B:
case ASiC_S_BASELINE_T:
case ASiC_S_BASELINE_LT:
case ASiC_E_BASELINE_B:
case ASiC_E_BASELINE_T:
case ASiC_E_BASELINE_LT:
return asicService;
default:
throw new IllegalArgumentException("Unrecognized format " + signatureLevel);
}
}
private SignatureParameters createParameters(final WSParameters wsParameters) throws DSSException {
if (wsParameters == null) {
return null;
}
final SignatureParameters params = new SignatureParameters();
setSignatureLevel(wsParameters, params);
setSignaturePackaging(wsParameters, params);
setSignedInfoCanonicalizationMethod(wsParameters, params);
setEncryptionAlgorithm(wsParameters, params);
setDigestAlgorithm(wsParameters, params);
setSigningDate(wsParameters, params);
setSigningCertificateAndChain(wsParameters, params);
setSignWithExpiredCertificate(wsParameters, params);
setDeterministicId(wsParameters, params);
setSignaturePolicy(wsParameters, params);
setClaimedSignerRole(wsParameters, params);
setContentIdentifierPrefix(wsParameters, params);
setContentIdentifierSuffix(wsParameters, params);
setCommitmentTypeIndication(wsParameters, params);
setSignerLocation(wsParameters, params);
setReferences(wsParameters, params);
setAsicSignatureForm(wsParameters, params);
setAsicMimeType(wsParameters, params);
setAsicZipComment(wsParameters, params);
setAsicEnclosedSignature(wsParameters, params);
return params;
}
private void setSignaturePolicy(WSParameters wsParameters, SignatureParameters params) {
final BLevelParameters.Policy signaturePolicy = wsParameters.getSignaturePolicy();
params.bLevel().setSignaturePolicy(signaturePolicy);
}
private void setSignerLocation(WSParameters wsParameters, SignatureParameters params) {
final BLevelParameters.SignerLocation signerLocation = wsParameters.getSignerLocation();
params.bLevel().setSignerLocation(signerLocation);
}
private void setCommitmentTypeIndication(WSParameters wsParameters, SignatureParameters params) {
final List<String> commitmentTypeIndication = wsParameters.getCommitmentTypeIndication();
params.bLevel().setCommitmentTypeIndications(commitmentTypeIndication);
}
private void setContentIdentifierSuffix(WSParameters wsParameters, SignatureParameters params) {
final String contentIdentifierSuffix = wsParameters.getContentIdentifierSuffix();
params.bLevel().setContentIdentifierSuffix(contentIdentifierSuffix);
}
private void setContentIdentifierPrefix(WSParameters wsParameters, SignatureParameters params) {
final String contentIdentifierPrefix = wsParameters.getContentIdentifierPrefix();
params.bLevel().setContentIdentifierPrefix(contentIdentifierPrefix);
}
private void setSignedInfoCanonicalizationMethod(WSParameters wsParameters, SignatureParameters params) {
final String signedInfoCanonicalizationMethod = wsParameters.getSignedInfoCanonicalizationMethod();
params.setSignedInfoCanonicalizationMethod(signedInfoCanonicalizationMethod);
}
private void setEncryptionAlgorithm(WSParameters wsParameters, SignatureParameters params) {
final EncryptionAlgorithm encryptionAlgorithm = wsParameters.getEncryptionAlgorithm();
params.setEncryptionAlgorithm(encryptionAlgorithm);
}
private void setDigestAlgorithm(final WSParameters wsParameters, final SignatureParameters params) {
final DigestAlgorithm digestAlgorithm = wsParameters.getDigestAlgorithm();
params.setDigestAlgorithm(digestAlgorithm);
}
private void setDeterministicId(final WSParameters wsParameters, final SignatureParameters params) {
final String deterministicId = wsParameters.getDeterministicId();
params.setDeterministicId(deterministicId);
}
private void setClaimedSignerRole(final WSParameters wsParameters, final SignatureParameters params) {
final List<String> claimedSignerRoles = wsParameters.getClaimedSignerRole();
if (claimedSignerRoles != null) {
for (final String claimedSignerRole : claimedSignerRoles) {
params.bLevel().addClaimedSignerRole(claimedSignerRole);
}
}
}
private void setSigningCertificateAndChain(final WSParameters wsParameters, final SignatureParameters params) {
final byte[] signingCertBytes = wsParameters.getSigningCertificateBytes();
if (signingCertBytes == null) {
return;
}
final X509Certificate x509SigningCertificate = DSSUtils.loadCertificate(signingCertBytes);
params.setSigningCertificate(x509SigningCertificate);
final List<ChainCertificate> chainCertificates = new ArrayList<ChainCertificate>();
chainCertificates.add(new ChainCertificate(x509SigningCertificate, true));
final List<WSChainCertificate> wsChainCertificateList = wsParameters.getChainCertificateList();
if (!DSSUtils.isEmpty(wsChainCertificateList)) {
for (final WSChainCertificate wsChainCertificate : wsChainCertificateList) {
final X509Certificate x509Certificate = DSSUtils.loadCertificate(wsChainCertificate.getX509Certificate());
final ChainCertificate chainCertificate = new ChainCertificate(x509Certificate, wsChainCertificate.isSignedAttribute());
if (!chainCertificates.contains(chainCertificate)) {
chainCertificates.add(chainCertificate);
}
}
}
params.setCertificateChain(chainCertificates);
}
/**
* Allows to change the default behaviour regarding the use of an expired certificate.
*
* @param wsParameters
* @param params
*/
private void setSignWithExpiredCertificate(final WSParameters wsParameters, final SignatureParameters params) {
final boolean signWithExpiredCertificate = wsParameters.getSignWithExpiredCertificate();
params.setSignWithExpiredCertificate(signWithExpiredCertificate);
}
private void setSigningDate(final WSParameters wsParameters, final SignatureParameters params) {
final Date signingDate = wsParameters.getSigningDate();
params.bLevel().setSigningDate(signingDate);
}
private void setSignaturePackaging(final WSParameters wsParameters, final SignatureParameters params) {
final SignaturePackaging signaturePackaging = wsParameters.getSignaturePackaging();
params.setSignaturePackaging(signaturePackaging);
}
private void setSignatureLevel(final WSParameters wsParameters, final SignatureParameters params) {
final SignatureLevel signatureLevel = wsParameters.getSignatureLevel();
params.setSignatureLevel(signatureLevel);
}
private void setReferences(final WSParameters wsParameters, final SignatureParameters params) {
final List<WSDSSReference> wsReferences = wsParameters.getReferences();
if (wsReferences == null) {
return;
}
final List<DSSReference> dssReferences = new ArrayList<DSSReference>();
for (final WSDSSReference wsDssReference : wsReferences) {
final DSSReference dssReference = new DSSReference();
dssReference.setId(wsDssReference.getId());
dssReference.setType(wsDssReference.getType());
dssReference.setUri(wsDssReference.getUri());
dssReference.setDigestMethodAlgorithm(wsDssReference.getDigestMethodAlgorithm());
final DSSDocument contentsDssDocument = DSSWSUtils.createDssDocument(wsDssReference.getContents());
dssReference.setContents(contentsDssDocument);
dssReference.setTransforms(wsDssReference.getTransforms());
dssReferences.add(dssReference);
}
params.setReferences(dssReferences);
}
private void setAsicZipComment(final WSParameters wsParameters, final SignatureParameters params) {
params.aSiC().setZipComment(wsParameters.getAsicZipComment());
}
private void setAsicMimeType(final WSParameters wsParameters, final SignatureParameters params) {
params.aSiC().setMimeType(wsParameters.getAsicMimeType());
}
private void setAsicSignatureForm(final WSParameters wsParameters, final SignatureParameters params) {
params.aSiC().setUnderlyingForm(wsParameters.getAsicSignatureForm());
}
private void setAsicEnclosedSignature(final WSParameters wsParameters, final SignatureParameters params) {
final DSSDocument dssDocument = DSSWSUtils.createDssDocument(wsParameters.getAsicEnclosedSignature());
params.aSiC().setEnclosedSignature(dssDocument);
}
@Override
public byte[] getDataToSign(final WSDocument wsDocument, final WSParameters wsParameters) throws DSSException {
String exceptionMessage;
try {
if (LOG.isInfoEnabled()) {
LOG.info("WsGetDataToSign: begin");
}
final SignatureParameters params = createParameters(wsParameters);
final DSSDocument dssDocument = DSSWSUtils.createDssDocument(wsDocument);
final DocumentSignatureService service = getServiceForSignatureLevel(params.getSignatureLevel());
final byte[] dataToSign = service.getDataToSign(dssDocument, params);
if (LOG.isInfoEnabled()) {
LOG.info("WsGetDataToSign: end");
}
return dataToSign;
} catch (Throwable e) {
exceptionMessage = e.getMessage();
LOG.error("WsGetDataToSign: ended with exception", e);
throw new DSSException(exceptionMessage);
}
}
@Override
public WSDocument signDocument(final WSDocument wsDocument, final WSParameters wsParameters, final byte[] signatureValue) throws DSSException {
String exceptionMessage;
try {
if (LOG.isInfoEnabled()) {
LOG.info("WsSignDocument: begin");
}
final SignatureParameters params = createParameters(wsParameters);
final DSSDocument dssDocument = DSSWSUtils.createDssDocument(wsDocument);
final DocumentSignatureService service = getServiceForSignatureLevel(params.getSignatureLevel());
final DSSDocument signatureDssDocument = service.signDocument(dssDocument, params, signatureValue);
WSDocument SignatureWsDocument = new WSDocument(signatureDssDocument);
if (LOG.isInfoEnabled()) {
LOG.info("WsSignDocument: end");
}
return SignatureWsDocument;
} catch (Throwable e) {
exceptionMessage = e.getMessage();
LOG.error("WsSignDocument: ended with exception", e);
throw new DSSException(exceptionMessage);
}
}
@Override
public WSDocument extendSignature(final WSDocument wsDocument, final WSParameters wsParameters) throws DSSException {
String exceptionMessage;
try {
if (LOG.isInfoEnabled()) {
LOG.info("WsExtendSignature: begin");
}
final SignatureParameters params = createParameters(wsParameters);
final DSSDocument dssDocument = DSSWSUtils.createDssDocument(wsDocument);
final DocumentSignatureService service = getServiceForSignatureLevel(params.getSignatureLevel());
final DSSDocument signatureDssDocument = service.extendDocument(dssDocument, params);
final WSDocument signatureWsDocument = new WSDocument(signatureDssDocument);
if (LOG.isInfoEnabled()) {
LOG.info("WsExtendSignature: end");
}
return signatureWsDocument;
} catch (Throwable e) {
exceptionMessage = e.getMessage();
LOG.error("WsExtendSignature: end with exception", e);
throw new DSSException(exceptionMessage);
}
}
}