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.io.OutputStreamWriter;
import java.nio.charset.Charset;
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.DOMResult;
import javax.xml.transform.dom.DOMSource;

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.Alias;
import br.net.woodstock.rockframework.security.digest.DigestType;
import br.net.woodstock.rockframework.security.sign.SignatureParameters;
import br.net.woodstock.rockframework.security.sign.SignatureType;
import br.net.woodstock.rockframework.security.sign.SignerException;
import br.net.woodstock.rockframework.security.store.PrivateKeyEntry;
import br.net.woodstock.rockframework.security.store.Store;
import br.net.woodstock.rockframework.security.store.StoreEntryType;
import br.net.woodstock.rockframework.util.Assert;
import br.net.woodstock.rockframework.xml.dom.XmlWriter;

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 static final String    XMLNS_ATTRIBUTE    = "xmlns";

  private DocumentBuilderFactory  documentBuilderFactory;

  private XMLSignatureFactory    xmlSignatureFactory;

  private SignedInfo        signedInfo;

  private KeyInfo          keyInfo;

  private SignatureParameters    request;

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

    this.request = request;

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

  @Override
  public byte[] sign(final byte[] data) {
    Assert.notEmpty(data, "data");
    try {
      Store store = this.request.getStore();
      Alias[] aliases = this.request.getAliases();

      byte[] currentData = data;

      for (Alias alias : aliases) {
        PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) store.get(alias, StoreEntryType.PRIVATE_KEY);
        PrivateKey privateKey = privateKeyEntry.getValue();
        Certificate[] chain = privateKeyEntry.getChain();
        X509Certificate certificate = (X509Certificate) chain[0];
        PublicKey publicKey = certificate.getPublicKey();

        String digestType = this.getDigestMethodName(certificate.getSigAlgName());
        DigestMethod digestMethod = this.xmlSignatureFactory.newDigestMethod(digestType, 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(this.getSignatureDigestName(certificate.getSigAlgName()), 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);

        Document outputDocument = this.documentBuilderFactory.newDocumentBuilder().newDocument();
        DOMResult domResult = new DOMResult(outputDocument);

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

        ByteArrayWriter writer = new ByteArrayWriter();
        XmlWriter.getInstance().write(outputDocument, writer, Charset.defaultCharset());

        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 {
      Store store = this.request.getStore();
      Alias[] aliases = this.request.getAliases();

      boolean valid = true;

      for (Alias alias : aliases) {
        PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) store.get(alias, StoreEntryType.PRIVATE_KEY);
        Certificate[] chain = privateKeyEntry.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.getElementsByTagName(XMLSigner.SIGNATURE_ELEMENT);
        if ((nodeList != null) && (nodeList.getLength() > 0)) {
          Node node = nodeList.item(0);
          if (node instanceof Element) {
            Element element = (Element) node;
            String attribute = element.getAttribute(XMLSigner.XMLNS_ATTRIBUTE);
            if (XMLSignature.XMLNS.equals(attribute)) {
              XmlWriter.getInstance().write(element, new OutputStreamWriter(System.out), Charset.defaultCharset());

              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);
    }
  }

  private String getDigestMethodName(final String name) {
    //SignatureType signatureType = SignatureType.getSignType(name);
    //DigestType digestType = signatureType.getDigestType();
    //return digestType.getDigestMethod();
    return null;
  }

  private String getSignatureDigestName(final String name) {
    SignatureType signatureType = SignatureType.getSignType(name);
    return signatureType.getSignatureMethod();
  }

}
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.