be.fedict.hsm.ws.impl.DigitalSignatureServicePortImpl.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.hsm.ws.impl.DigitalSignatureServicePortImpl.java

Source

/*
 * HSM Proxy Project.
 * Copyright (C) 2013 FedICT.
 * Copyright (C) 2013 Frank Cornelis.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software 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 software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.hsm.ws.impl;

import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.JAXBElement;
import javax.xml.ws.BindingType;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.soap.SOAPBinding;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import be.fedict.hsm.model.SignatureService;
import be.fedict.hsm.ws.DSSConstants;
import be.fedict.hsm.ws.ResultMajor;
import be.fedict.hsm.ws.jaxb.dss.AnyType;
import be.fedict.hsm.ws.jaxb.dss.Base64Signature;
import be.fedict.hsm.ws.jaxb.dss.DocumentHash;
import be.fedict.hsm.ws.jaxb.dss.InputDocuments;
import be.fedict.hsm.ws.jaxb.dss.KeySelector;
import be.fedict.hsm.ws.jaxb.dss.ObjectFactory;
import be.fedict.hsm.ws.jaxb.dss.ResponseBaseType;
import be.fedict.hsm.ws.jaxb.dss.Result;
import be.fedict.hsm.ws.jaxb.dss.SignRequest;
import be.fedict.hsm.ws.jaxb.dss.SignResponse;
import be.fedict.hsm.ws.jaxb.dss.SignatureObject;
import be.fedict.hsm.ws.jaxb.dss.VerifyRequest;
import be.fedict.hsm.ws.jaxb.hsm.GetAliasesRequest;
import be.fedict.hsm.ws.jaxb.hsm.GetCertificateChainRequest;
import be.fedict.hsm.ws.jaxb.xmldsig.DigestMethodType;
import be.fedict.hsm.ws.jaxb.xmldsig.KeyInfoType;
import be.fedict.hsm.ws.jaxb.xmldsig.X509DataType;
import be.fedict.hsm.ws.jaxws.DigitalSignatureServicePortType;

@WebService(endpointInterface = "be.fedict.hsm.ws.jaxws.DigitalSignatureServicePortType", targetNamespace = "urn:be:fedict:hsm-proxy:ws", serviceName = "DigitalSignatureService")
@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
@HandlerChain(file = "/hsm-proxy-ws-handlers.xml")
public class DigitalSignatureServicePortImpl implements DigitalSignatureServicePortType {

    private static final Log LOG = LogFactory.getLog(DigitalSignatureServicePortImpl.class);

    @EJB
    private SignatureService signatureService;

    @Resource
    private WebServiceContext webServiceContext;

    private final ObjectFactory objectFactory;

    private final be.fedict.hsm.ws.jaxb.xmldsig.ObjectFactory xmldsigObjectFactory;

    public DigitalSignatureServicePortImpl() {
        this.objectFactory = new ObjectFactory();
        this.xmldsigObjectFactory = new be.fedict.hsm.ws.jaxb.xmldsig.ObjectFactory();
    }

    @Override
    @WebMethod
    @WebResult(name = "VerifyResponse", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "VerifyResponse")
    public ResponseBaseType verify(
            @WebParam(name = "VerifyRequest", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "VerifyRequest") VerifyRequest verifyRequest) {
        return null;
    }

    @Override
    @WebMethod
    @WebResult(name = "SignResponse", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "SignResponse")
    public SignResponse sign(
            @WebParam(name = "SignRequest", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "SignRequest") SignRequest signRequest) {
        LOG.debug("sign");
        Principal userPrincipal = this.webServiceContext.getUserPrincipal();
        if (null != userPrincipal) {
            String userName = userPrincipal.getName();
            LOG.debug("username: " + userName);
        } else {
            LOG.debug("no user principal");
        }
        String requestId = signRequest.getRequestID();
        String digestMethodAlgorithm = null;
        byte[] digestValue = null;
        String keyAlias = null;
        InputDocuments inputDocuments = signRequest.getInputDocuments();
        if (null == inputDocuments) {
            LOG.error("missing dss:InputDocuments");
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }
        List<Object> inputDocumentsContent = inputDocuments.getDocumentOrTransformedDataOrDocumentHash();
        for (Object object : inputDocumentsContent) {
            if (object instanceof DocumentHash) {
                DocumentHash documentHash = (DocumentHash) object;
                DigestMethodType digestMethod = documentHash.getDigestMethod();
                digestMethodAlgorithm = digestMethod.getAlgorithm();
                digestValue = documentHash.getDigestValue();
            }
        }
        AnyType optionalInputs = signRequest.getOptionalInputs();
        if (null == optionalInputs) {
            LOG.error("missing dss:OptionalInputs");
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }
        List<Object> optionalInputsContent = optionalInputs.getAny();
        for (Object object : optionalInputsContent) {
            if (object instanceof KeySelector) {
                KeySelector keySelector = (KeySelector) object;
                KeyInfoType keyInfo = keySelector.getKeyInfo();
                List<Object> keyInfoContent = keyInfo.getContent();
                for (Object keyInfoObject : keyInfoContent) {
                    if (keyInfoObject instanceof JAXBElement) {
                        JAXBElement jaxbElement = (JAXBElement) keyInfoObject;
                        keyAlias = (String) jaxbElement.getValue();
                    }
                }
            }
        }

        if (null == digestMethodAlgorithm) {
            LOG.error("missing digest algo");
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }
        if (null == digestValue) {
            LOG.error("missing digest value");
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }
        if (null == keyAlias) {
            LOG.error("missing dss:KeySelector");
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }
        LOG.debug("digest algo: " + digestMethodAlgorithm);
        LOG.debug("key alias: " + keyAlias);

        byte[] signatureValue;
        try {
            signatureValue = this.signatureService.sign(digestMethodAlgorithm, digestValue, keyAlias);
        } catch (NoSuchAlgorithmException e) {
            return errorSignResponse(ResultMajor.REQUESTER_ERROR);
        }

        SignResponse signResponse = this.objectFactory.createSignResponse();
        signResponse.setRequestID(requestId);
        signResponse.setProfile(DSSConstants.HSM_PROXY_DSS_PROFILE_URI);

        Result result = this.objectFactory.createResult();
        signResponse.setResult(result);
        result.setResultMajor(ResultMajor.SUCCESS.getUri());
        result.setResultMinor(DSSConstants.RESULT_MINOR_VALID_ON_ALL_DOCS);

        SignatureObject signatureObject = this.objectFactory.createSignatureObject();
        signResponse.setSignatureObject(signatureObject);
        Base64Signature base64Signature = this.objectFactory.createBase64Signature();
        signatureObject.setBase64Signature(base64Signature);
        base64Signature.setValue(signatureValue);

        return signResponse;
    }

    private SignResponse errorSignResponse(ResultMajor resultMajor) {
        SignResponse signResponse = this.objectFactory.createSignResponse();
        Result result = this.objectFactory.createResult();
        signResponse.setResult(result);
        result.setResultMajor(resultMajor.getUri());
        return signResponse;
    }

    private ResponseBaseType errorResponse(ResultMajor resultMajor) {
        ResponseBaseType response = this.objectFactory.createResponseBaseType();
        Result result = this.objectFactory.createResult();
        response.setResult(result);
        result.setResultMajor(resultMajor.getUri());
        return response;
    }

    @Override
    @WebMethod(operationName = "get-aliases")
    @WebResult(name = "Response", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "GetAliasesResponse")
    public ResponseBaseType getAliases(
            @WebParam(name = "GetAliasesRequest", targetNamespace = "urn:be:fedict:hsm-proxy:ws:dss:profiles:hsm-proxy:1.0", partName = "GetAliasesRequest") GetAliasesRequest getAliasesRequest) {
        String requestId = getAliasesRequest.getRequestID();
        Set<String> aliases = this.signatureService.getAliases();
        ResponseBaseType response = this.objectFactory.createResponseBaseType();
        response.setRequestID(requestId);
        response.setProfile(DSSConstants.HSM_PROXY_DSS_PROFILE_URI);

        Result result = this.objectFactory.createResult();
        response.setResult(result);
        result.setResultMajor(ResultMajor.SUCCESS.getUri());

        AnyType optionalOutputs = this.objectFactory.createAnyType();
        response.setOptionalOutputs(optionalOutputs);
        for (String alias : aliases) {
            KeySelector keySelector = this.objectFactory.createKeySelector();
            optionalOutputs.getAny().add(keySelector);
            KeyInfoType keyInfo = this.xmldsigObjectFactory.createKeyInfoType();
            keySelector.setKeyInfo(keyInfo);
            keyInfo.getContent().add(this.xmldsigObjectFactory.createKeyName(alias));
        }
        response.setOptionalOutputs(optionalOutputs);

        return response;
    }

    @Override
    @WebMethod(operationName = "get-certificate-chain")
    @WebResult(name = "Response", targetNamespace = "urn:oasis:names:tc:dss:1.0:core:schema", partName = "GetCertificateChainResponse")
    public ResponseBaseType getCertificateChain(
            @WebParam(name = "GetCertificateChainRequest", targetNamespace = "urn:be:fedict:hsm-proxy:ws:dss:profiles:hsm-proxy:1.0", partName = "GetCertificateChainRequest") GetCertificateChainRequest getCertificateChainRequest) {
        String requestId = getCertificateChainRequest.getRequestID();
        AnyType optionalInputs = getCertificateChainRequest.getOptionalInputs();
        if (null == optionalInputs) {
            LOG.error("missing dss:OptionalInputs");
            return errorResponse(ResultMajor.REQUESTER_ERROR);
        }
        List<Object> optionalInputsContent = optionalInputs.getAny();
        String alias = null;
        for (Object object : optionalInputsContent) {
            if (object instanceof KeySelector) {
                KeySelector keySelector = (KeySelector) object;
                KeyInfoType keyInfo = keySelector.getKeyInfo();
                if (null == keyInfo) {
                    LOG.error("missing ds:KeyInfo");
                    return errorResponse(ResultMajor.REQUESTER_ERROR);
                }
                List<Object> keyInfoContent = keyInfo.getContent();
                for (Object keyInfoObject : keyInfoContent) {
                    if (keyInfoObject instanceof JAXBElement) {
                        JAXBElement jaxbElement = (JAXBElement) keyInfoObject;
                        alias = (String) jaxbElement.getValue();
                    }
                }
            }
        }
        if (null == alias) {
            LOG.error("missing dss:KeySelector/ds:KeyInfo/ds:KeyName");
            return errorResponse(ResultMajor.REQUESTER_ERROR);
        }
        LOG.debug("get certificate chain for alias: " + alias);
        Certificate[] certificateChain;
        try {
            certificateChain = this.signatureService.getCertificateChain(alias);
        } catch (NoSuchAlgorithmException e) {
            LOG.error("no such algo: " + e.getMessage());
            return errorResponse(ResultMajor.REQUESTER_ERROR);
        }
        if (null == certificateChain) {
            LOG.error("no cert chain found");
            return errorResponse(ResultMajor.REQUESTER_ERROR);
        }
        ResponseBaseType response = this.objectFactory.createResponseBaseType();
        response.setRequestID(requestId);
        response.setProfile(DSSConstants.HSM_PROXY_DSS_PROFILE_URI);

        Result result = this.objectFactory.createResult();
        response.setResult(result);
        result.setResultMajor(ResultMajor.SUCCESS.getUri());

        KeyInfoType keyInfo = this.xmldsigObjectFactory.createKeyInfoType();
        AnyType optionalOutputs = this.objectFactory.createAnyType();
        optionalOutputs.getAny().add(this.xmldsigObjectFactory.createKeyInfo(keyInfo));
        response.setOptionalOutputs(optionalOutputs);

        List<Object> keyInfoContent = keyInfo.getContent();
        X509DataType x509Data = this.xmldsigObjectFactory.createX509DataType();
        keyInfoContent.add(this.xmldsigObjectFactory.createX509Data(x509Data));

        List<Object> x509DataContent = x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName();
        for (Certificate certificate : certificateChain) {
            try {
                x509DataContent
                        .add(this.xmldsigObjectFactory.createX509DataTypeX509Certificate(certificate.getEncoded()));
            } catch (CertificateEncodingException e) {
                LOG.error("certificate encoding error: " + e.getMessage());
                return errorResponse(ResultMajor.RESPONDER_ERROR);
            }
        }

        return response;
    }
}