test.unit.be.e_contract.dssp.client.SignResponseFactory.java Source code

Java tutorial

Introduction

Here is the source code for test.unit.be.e_contract.dssp.client.SignResponseFactory.java

Source

/*
 * Digital Signature Service Protocol Project.
 * Copyright (C) 2013-2014 e-Contract.be BVBA.
 *
 * 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 test.unit.be.e_contract.dssp.client;

import java.io.ByteArrayOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xml.security.utils.Base64;
import org.joda.time.DateTime;
import org.joda.time.chrono.ISOChronology;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import be.e_contract.dssp.ws.DigitalSignatureServiceConstants;
import be.e_contract.dssp.ws.jaxb.dss.AnyType;
import be.e_contract.dssp.ws.jaxb.dss.ObjectFactory;
import be.e_contract.dssp.ws.jaxb.dss.Result;
import be.e_contract.dssp.ws.jaxb.dss.SignResponse;
import be.e_contract.dssp.ws.jaxb.saml.protocol.NameIdentifierType;
import be.e_contract.dssp.ws.jaxb.wsa.AttributedURIType;
import be.e_contract.dssp.ws.jaxb.wsa.RelatesToType;
import be.e_contract.dssp.ws.jaxb.wsse.ReferenceType;
import be.e_contract.dssp.ws.jaxb.wsse.SecurityTokenReferenceType;
import be.e_contract.dssp.ws.jaxb.wsu.AttributedDateTime;
import be.e_contract.dssp.ws.jaxb.wsu.TimestampType;

public class SignResponseFactory {

    private SignResponseFactory() {
        super();
    }

    public static String createSignResponse(String responseId, String destination, String inResponseTo,
            String tokenId, byte[] tokenKey) {
        return createSignResponse(responseId, destination, inResponseTo, tokenId, tokenKey,
                DigitalSignatureServiceConstants.PENDING_RESULT_MAJOR, null, null);
    }

    public static String createSignResponse(String responseId, String destination, String inResponseTo,
            String tokenId, byte[] tokenKey, String resultMajor, String resultMinor, String signerIdentity) {
        ObjectFactory dssObjectFactory = new ObjectFactory();
        be.e_contract.dssp.ws.jaxb.dss.async.ObjectFactory asyncObjectFactory = new be.e_contract.dssp.ws.jaxb.dss.async.ObjectFactory();
        be.e_contract.dssp.ws.jaxb.wsa.ObjectFactory wsaObjectFactory = new be.e_contract.dssp.ws.jaxb.wsa.ObjectFactory();
        be.e_contract.dssp.ws.jaxb.wsu.ObjectFactory wsuObjectFactory = new be.e_contract.dssp.ws.jaxb.wsu.ObjectFactory();
        be.e_contract.dssp.ws.jaxb.saml.protocol.ObjectFactory samlObjectFactory = new be.e_contract.dssp.ws.jaxb.saml.protocol.ObjectFactory();

        SignResponse signResponse = dssObjectFactory.createSignResponse();
        signResponse.setProfile(DigitalSignatureServiceConstants.PROFILE);
        Result result = dssObjectFactory.createResult();
        signResponse.setResult(result);
        result.setResultMajor(resultMajor);
        if (null != resultMinor) {
            result.setResultMinor(resultMinor);
        }

        AnyType optionalOutputs = dssObjectFactory.createAnyType();
        signResponse.setOptionalOutputs(optionalOutputs);

        optionalOutputs.getAny().add(asyncObjectFactory.createResponseID(responseId));

        RelatesToType relatesTo = wsaObjectFactory.createRelatesToType();
        optionalOutputs.getAny().add(wsaObjectFactory.createRelatesTo(relatesTo));
        relatesTo.setValue(inResponseTo);

        TimestampType timestamp = wsuObjectFactory.createTimestampType();
        optionalOutputs.getAny().add(wsuObjectFactory.createTimestamp(timestamp));
        AttributedDateTime created = wsuObjectFactory.createAttributedDateTime();
        timestamp.setCreated(created);
        DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime()
                .withChronology(ISOChronology.getInstanceUTC());
        DateTime createdDateTime = new DateTime();
        created.setValue(dateTimeFormatter.print(createdDateTime));
        AttributedDateTime expires = wsuObjectFactory.createAttributedDateTime();
        timestamp.setExpires(expires);
        DateTime expiresDateTime = createdDateTime.plusMinutes(5);
        expires.setValue(dateTimeFormatter.print(expiresDateTime));

        AttributedURIType to = wsaObjectFactory.createAttributedURIType();
        optionalOutputs.getAny().add(wsaObjectFactory.createTo(to));
        to.setValue(destination);

        if (null != signerIdentity) {
            NameIdentifierType nameIdentifier = samlObjectFactory.createNameIdentifierType();
            nameIdentifier.setValue(signerIdentity);
            nameIdentifier.setFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName");
            optionalOutputs.getAny().add(dssObjectFactory.createSignerIdentity(nameIdentifier));
        }

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder documentBuilder;
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("DOM error: " + e.getMessage(), e);
        }
        Document document = documentBuilder.newDocument();

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class,
                    be.e_contract.dssp.ws.jaxb.wsa.ObjectFactory.class,
                    be.e_contract.dssp.ws.jaxb.wsu.ObjectFactory.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.marshal(signResponse, document);
        } catch (JAXBException ex) {
            throw new RuntimeException(ex);
        }
        try {
            sign(document, tokenId, tokenKey);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer;
        try {
            transformer = transformerFactory.newTransformer();
        } catch (TransformerConfigurationException e) {
            throw new RuntimeException("JAXP config error: " + e.getMessage(), e);
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            transformer.transform(new DOMSource(document), new StreamResult(byteArrayOutputStream));
        } catch (TransformerException e) {
            throw new RuntimeException("JAXP error: " + e.getMessage(), e);
        }

        return Base64.encode(byteArrayOutputStream.toByteArray());
    }

    private static void sign(Document document, String tokenId, byte[] tokenKey) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, MarshalException, XMLSignatureException {
        Key key = new SecretKeySpec(tokenKey, "HMACSHA1");
        Node parentElement = document
                .getElementsByTagNameNS("urn:oasis:names:tc:dss:1.0:core:schema", "OptionalOutputs").item(0);
        DOMSignContext domSignContext = new DOMSignContext(key, parentElement);
        domSignContext.setDefaultNamespacePrefix("ds");
        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");

        List<Transform> transforms = new LinkedList<Transform>();
        transforms.add(xmlSignatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
        transforms.add(
                xmlSignatureFactory.newTransform(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null));
        Reference reference = xmlSignatureFactory.newReference("",
                xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null), transforms, null, null);

        SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(
                xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
                        (C14NMethodParameterSpec) null),
                xmlSignatureFactory.newSignatureMethod(SignatureMethod.HMAC_SHA1, null),
                Collections.singletonList(reference));

        Element securityTokenReferenceElement = getSecurityTokenReference(tokenId);

        KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory();
        DOMStructure securityTokenReferenceDOMStructure = new DOMStructure(securityTokenReferenceElement);
        KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(securityTokenReferenceDOMStructure));

        XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);
        xmlSignature.sign(domSignContext);
    }

    private static Element getSecurityTokenReference(String tokenId) {
        be.e_contract.dssp.ws.jaxb.wsse.ObjectFactory wsseObjectFactory = new be.e_contract.dssp.ws.jaxb.wsse.ObjectFactory();

        SecurityTokenReferenceType securityTokenReference = wsseObjectFactory.createSecurityTokenReferenceType();
        ReferenceType reference = wsseObjectFactory.createReferenceType();
        reference.setValueType(DigitalSignatureServiceConstants.WS_SEC_CONV_TOKEN_TYPE);
        reference.setURI(tokenId);
        securityTokenReference.getAny().add(wsseObjectFactory.createReference(reference));

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder documentBuilder;
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("DOM error: " + e.getMessage(), e);
        }
        Document document = documentBuilder.newDocument();

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(be.e_contract.dssp.ws.jaxb.wsse.ObjectFactory.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.marshal(wsseObjectFactory.createSecurityTokenReference(securityTokenReference), document);
        } catch (JAXBException e) {
            throw new RuntimeException("JAXB error: " + e.getMessage(), e);
        }
        return document.getDocumentElement();
    }
}