| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "<WebSig>" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2001, Institute for |
| * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>. |
| * The development of this software was partly funded by the European |
| * Commission in the <WebSig> project in the ISIS Programme. |
| * For more information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| package org.apache.xml.security.signature; |
| |
| |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| |
| import javax.crypto.SecretKey; |
| import javax.crypto.spec.SecretKeySpec; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.apache.xml.security.algorithms.SignatureAlgorithm; |
| import org.apache.xml.security.c14n.CanonicalizationException; |
| import org.apache.xml.security.c14n.Canonicalizer; |
| import org.apache.xml.security.c14n.InvalidCanonicalizerException; |
| import org.apache.xml.security.exceptions.XMLSecurityException; |
| import org.apache.xml.security.utils.Constants; |
| import org.apache.xml.security.utils.ElementProxy; |
| import org.apache.xml.security.utils.XMLUtils; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.SAXException; |
| |
| |
| /** |
| * Handles <code><ds:SignedInfo></code> elements |
| * This <code>SignedInfo<code> element includes the canonicalization algorithm, |
| * a signature algorithm, and one or more references |
| * @author Christian Geuer-Pollmann |
| */ |
| public class SignedInfo extends Manifest { |
| |
| /** Field _signatureAlgorithm */ |
| private SignatureAlgorithm _signatureAlgorithm = null; |
| |
| /** Field _c14nizedBytes */ |
| private byte[] _c14nizedBytes = null; |
| |
| /** |
| * Overwrites {@link Manifest#addDocument} because it creates another Element. |
| * |
| * @param doc the {@link Document} in which <code>XMLsignature</code> will be placed |
| * @throws XMLSecurityException |
| */ |
| public SignedInfo(Document doc) throws XMLSecurityException { |
| this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA, Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); |
| } |
| |
| /** |
| * Constructs {@link SignedInfo} using given Canoicaliztion algorithm and Signature algorithm |
| * |
| * @param doc <code>SignedInfo</code> is placed in this document |
| * @param CanonicalizationMethodURI URI representation of the Canonicalization method |
| * @param SignatureMethodURI URI representation of the Digest and Signature algorithm |
| * @throws XMLSecurityException |
| */ |
| public SignedInfo( |
| Document doc, String SignatureMethodURI, String CanonicalizationMethodURI) |
| throws XMLSecurityException { |
| this(doc, SignatureMethodURI, 0, CanonicalizationMethodURI); |
| } |
| |
| /** |
| * Constructor SignedInfo |
| * |
| * @param doc |
| * @param CanonicalizationMethodURI |
| * @param SignatureMethodURI |
| * @param HMACOutputLength |
| * @throws XMLSecurityException |
| */ |
| public SignedInfo( |
| Document doc, String SignatureMethodURI, int HMACOutputLength, String CanonicalizationMethodURI) |
| throws XMLSecurityException { |
| |
| super(doc); |
| |
| // XMLUtils.addReturnToElement(this._constructionElement); |
| { |
| Element canonElem = XMLUtils.createElementInSignatureSpace(this._doc, |
| Constants._TAG_CANONICALIZATIONMETHOD); |
| |
| canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, |
| CanonicalizationMethodURI); |
| this._constructionElement.appendChild(canonElem); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| { |
| if (HMACOutputLength > 0) { |
| this._signatureAlgorithm = new SignatureAlgorithm(this._doc, |
| SignatureMethodURI, HMACOutputLength); |
| } else { |
| this._signatureAlgorithm = new SignatureAlgorithm(this._doc, |
| SignatureMethodURI); |
| } |
| |
| this._constructionElement |
| .appendChild(this._signatureAlgorithm.getElement()); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| } |
| |
| public SignedInfo( |
| Document doc, Element SignatureMethodElem, Element CanonicalizationMethodElem) |
| throws XMLSecurityException { |
| |
| super(doc); |
| |
| this._constructionElement.appendChild(CanonicalizationMethodElem); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| |
| this._signatureAlgorithm = new SignatureAlgorithm(SignatureMethodElem, null); |
| |
| this._constructionElement |
| .appendChild(this._signatureAlgorithm.getElement()); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| |
| /** |
| * Build a {@link SignedInfo} from an {@link Element} |
| * |
| * @param element <code>SignedInfo</code> |
| * @param BaseURI the URI of the resource where the XML instance was stored |
| * @throws XMLSecurityException |
| * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">Question</A> |
| * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html">Answer</A> |
| */ |
| public SignedInfo(Element element, String BaseURI) |
| throws XMLSecurityException { |
| |
| // Parse the Reference children and Id attribute in the Manifest |
| super(element, BaseURI); |
| |
| /* canonicalize ds:SignedInfo, reparse it into a new document |
| * and replace the original not-canonicalized ds:SignedInfo by |
| * the re-parsed canonicalized one. |
| */ |
| try { |
| Canonicalizer c14nizer = |
| Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
| |
| this._c14nizedBytes = |
| c14nizer.canonicalizeSubtree(this._constructionElement); |
| |
| javax.xml.parsers.DocumentBuilderFactory dbf = |
| javax.xml.parsers.DocumentBuilderFactory.newInstance(); |
| |
| dbf.setNamespaceAware(true); |
| |
| javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); |
| org.w3c.dom.Document newdoc = |
| db.parse(new ByteArrayInputStream(this._c14nizedBytes)); |
| Node imported = this._doc.importNode(newdoc.getDocumentElement(), |
| true); |
| |
| this._constructionElement.getParentNode().replaceChild(imported, |
| this._constructionElement); |
| |
| this._constructionElement = (Element) imported; |
| } catch (ParserConfigurationException ex) { |
| throw new XMLSecurityException("empty", ex); |
| } catch (IOException ex) { |
| throw new XMLSecurityException("empty", ex); |
| } catch (SAXException ex) { |
| throw new XMLSecurityException("empty", ex); |
| } |
| |
| this._signatureAlgorithm = |
| new SignatureAlgorithm(this.getSignatureMethodElement(), |
| this.getBaseURI()); |
| } |
| |
| /** |
| * Tests core validation process |
| * |
| * @return true if verification was successful |
| * @throws MissingResourceFailureException |
| * @throws XMLSecurityException |
| */ |
| public boolean verify() |
| throws MissingResourceFailureException, XMLSecurityException { |
| return super.verifyReferences(false); |
| } |
| |
| /** |
| * Tests core validation process |
| * |
| * @param followManifests defines whether the verification process has to verify referenced <CODE>ds:Manifest</CODE>s, too |
| * @return true if verification was successful |
| * @throws MissingResourceFailureException |
| * @throws XMLSecurityException |
| */ |
| public boolean verify(boolean followManifests) |
| throws MissingResourceFailureException, XMLSecurityException { |
| return super.verifyReferences(followManifests); |
| } |
| |
| /** |
| * Returns getCanonicalizedOctetStream |
| * |
| * @return the canonicalization result octedt stream of <code>SignedInfo</code> element |
| * @throws CanonicalizationException |
| * @throws IOException |
| * @throws InvalidCanonicalizerException |
| * @throws XMLSecurityException |
| */ |
| public byte[] getCanonicalizedOctetStream() |
| throws CanonicalizationException, InvalidCanonicalizerException, |
| IOException, XMLSecurityException { |
| |
| if ((this._c14nizedBytes == null) |
| && (this._state == ElementProxy.MODE_SIGN)) { |
| Canonicalizer c14nizer = |
| Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
| |
| this._c14nizedBytes = |
| c14nizer.canonicalizeSubtree(this._constructionElement); |
| } |
| |
| // make defensive copy |
| byte[] output = new byte[this._c14nizedBytes.length]; |
| |
| System.arraycopy(this._c14nizedBytes, 0, output, 0, output.length); |
| |
| return output; |
| } |
| |
| /** |
| * Returns the Canonicalization method URI |
| * |
| * @return the Canonicalization method URI |
| */ |
| public String getCanonicalizationMethodURI() { |
| |
| NodeList children = this._constructionElement.getChildNodes(); |
| |
| for (int i = 0; i < children.getLength(); i++) { |
| Node n = children.item(i); |
| |
| if (n.getNodeType() == Node.ELEMENT_NODE) { |
| boolean found = true; |
| |
| try { |
| XMLUtils.guaranteeThatElementInSignatureSpace((Element) n, |
| Constants._TAG_CANONICALIZATIONMETHOD); |
| } catch (XMLSecurityException ex) { |
| found = false; |
| } |
| |
| if (found) { |
| return ((Element) n).getAttributeNS(null, Constants._ATT_ALGORITHM); |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the Signature method URI |
| * |
| * @return the Signature method URI |
| */ |
| public String getSignatureMethodURI() { |
| |
| Element signatureElement = this.getSignatureMethodElement(); |
| |
| if (signatureElement != null) { |
| return signatureElement.getAttributeNS(null, Constants._ATT_ALGORITHM); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Method getSignatureMethodElement |
| * |
| * |
| */ |
| public Element getSignatureMethodElement() { |
| |
| NodeList children = this._constructionElement.getChildNodes(); |
| |
| for (int i = 0; i < children.getLength(); i++) { |
| Node n = children.item(i); |
| |
| log.debug("Looking for SignatureMethodURI in " + n); |
| |
| if (n.getNodeType() == Node.ELEMENT_NODE) { |
| boolean found = true; |
| |
| try { |
| XMLUtils.guaranteeThatElementInSignatureSpace((Element) n, |
| Constants._TAG_SIGNATUREMETHOD); |
| } catch (XMLSecurityException ex) { |
| found = false; |
| } |
| |
| if (found) { |
| return (Element) n; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Creates a SecretKey for the appropriate Mac algorithm based on a |
| * byte[] array password. |
| * |
| * @param secretKeyBytes |
| * |
| * @throws XMLSecurityException |
| */ |
| public SecretKey createSecretKey(byte[] secretKeyBytes) |
| throws XMLSecurityException { |
| |
| return new SecretKeySpec(secretKeyBytes, |
| this._signatureAlgorithm |
| .getJCEAlgorithmString()); |
| } |
| |
| /** |
| * Method getBaseLocalName |
| * |
| * |
| */ |
| public String getBaseLocalName() { |
| return Constants._TAG_SIGNEDINFO; |
| } |
| } |