Package br.net.woodstock.rockframework.security.sign.impl

Source Code of br.net.woodstock.rockframework.security.sign.impl.XMLSigner

/*
* This file is part of rockframework.
*
* rockframework is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* rockframework 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>;.
*/
package br.net.woodstock.rockframework.security.sign.impl;

import java.io.ByteArrayInputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;

import javax.xml.crypto.KeySelector;
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.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import br.net.woodstock.rockframework.io.ByteArrayWriter;
import br.net.woodstock.rockframework.security.Identity;
import br.net.woodstock.rockframework.security.sign.SignatureParameters;
import br.net.woodstock.rockframework.security.sign.SignerException;
import br.net.woodstock.rockframework.util.Assert;

public class XMLSigner extends AbstractSigner {

  private static final String    SIGNATURE_FACTORY  = "DOM";

  private static final String    REFERENCE_URI    = "";

  private static final String    SIGNATURE_ELEMENT  = "Signature";

  private DocumentBuilderFactory  documentBuilderFactory;

  private XMLSignatureFactory    xmlSignatureFactory;

  private SignedInfo        signedInfo;

  private KeyInfo          keyInfo;

  private SignatureParameters    parameters;

  public XMLSigner(final SignatureParameters parameters) {
    super();
    Assert.notNull(parameters, "parameters");

    this.parameters = parameters;

    this.xmlSignatureFactory = XMLSignatureFactory.getInstance(XMLSigner.SIGNATURE_FACTORY);
    this.documentBuilderFactory = DocumentBuilderFactory.newInstance();
    this.documentBuilderFactory.setNamespaceAware(true);
  }

  @Override
  public byte[] sign(final byte[] data) {
    Assert.notEmpty(data, "data");
    try {
      Identity[] identities = this.parameters.getIdentities();

      byte[] currentData = data;

      for (Identity identity : identities) {
        PrivateKey privateKey = identity.getPrivateKey();
        Certificate[] chain = identity.getChain();
        X509Certificate certificate = (X509Certificate) chain[0];
        PublicKey publicKey = certificate.getPublicKey();

        DigestMethod digestMethod = this.xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null);
        List<Transform> transforms = Collections.singletonList(this.xmlSignatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
        Reference reference = this.xmlSignatureFactory.newReference(XMLSigner.REFERENCE_URI, digestMethod, transforms, null, null);

        CanonicalizationMethod canonicalizationMethod = this.xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null);
        SignatureMethod signatureMethod = this.xmlSignatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);

        this.signedInfo = this.xmlSignatureFactory.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(reference));

        KeyInfoFactory keyInfoFactory = this.xmlSignatureFactory.getKeyInfoFactory();
        KeyValue keyValue = keyInfoFactory.newKeyValue(publicKey);
        this.keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(keyValue));

        ByteArrayInputStream inputStream = new ByteArrayInputStream(currentData);

        Document document = this.documentBuilderFactory.newDocumentBuilder().parse(inputStream);
        DOMSignContext signContext = new DOMSignContext(privateKey, document.getDocumentElement());
        XMLSignature signature = this.xmlSignatureFactory.newXMLSignature(this.signedInfo, this.keyInfo);

        signature.sign(signContext);

        ByteArrayWriter writer = new ByteArrayWriter();
        StreamResult streamResult = new StreamResult(writer);

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), streamResult);

        currentData = writer.toByteArray();
      }
      return currentData;
    } catch (Exception e) {
      throw new SignerException(e);
    }
  }

  @Override
  public boolean verify(final byte[] data, final byte[] signature) {
    Assert.notEmpty(data, "data");
    Assert.notEmpty(signature, "signature");
    try {
      Identity[] identities = this.parameters.getIdentities();

      boolean valid = true;

      for (Identity identity : identities) {
        Certificate[] chain = identity.getChain();
        X509Certificate certificate = (X509Certificate) chain[0];
        PublicKey publicKey = certificate.getPublicKey();

        ByteArrayInputStream inputStream = new ByteArrayInputStream(signature);
        Document document = this.documentBuilderFactory.newDocumentBuilder().parse(inputStream);

        NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, XMLSigner.SIGNATURE_ELEMENT);
        if ((nodeList != null) && (nodeList.getLength() > 0)) {
          Node node = nodeList.item(0);
          if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element element = (Element) node;
            DOMValidateContext domValidateContext = new DOMValidateContext(KeySelector.singletonKeySelector(publicKey), element);
            XMLSignature xmlSignature = this.xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
            valid = xmlSignature.getSignatureValue().validate(domValidateContext);
            if (!valid) {
              break;
            }
          }
        } else {
          valid = false;
          break;
        }
      }
      return valid;
    } catch (Exception e) {
      throw new SignerException(e);
    }
  }

}
TOP

Related Classes of br.net.woodstock.rockframework.security.sign.impl.XMLSigner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.