| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Copyright 1999-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package com.sun.org.apache.xml.internal.security.signature; |
| |
| |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm; |
| import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; |
| import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
| import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; |
| import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
| import com.sun.org.apache.xml.internal.security.transforms.InvalidTransformException; |
| import com.sun.org.apache.xml.internal.security.transforms.Transform; |
| import com.sun.org.apache.xml.internal.security.transforms.TransformationException; |
| import com.sun.org.apache.xml.internal.security.transforms.Transforms; |
| import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces; |
| import com.sun.org.apache.xml.internal.security.utils.Base64; |
| import com.sun.org.apache.xml.internal.security.utils.Constants; |
| import com.sun.org.apache.xml.internal.security.utils.DigesterOutputStream; |
| import com.sun.org.apache.xml.internal.security.utils.IdResolver; |
| import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; |
| import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; |
| import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
| import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; |
| import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Text; |
| |
| |
| /** |
| * Handles <code><ds:Reference></code> elements. |
| * |
| * This includes: |
| * |
| * Constuct a <CODE>ds:Reference</CODE> from an {@link org.w3c.dom.Element}. |
| * |
| * <p>Create a new reference</p> |
| * <pre> |
| * Document _doc; |
| * MessageDigestAlgorithm sha1 = MessageDigestAlgorithm.getInstance("http://#sha1"); |
| * Reference ref = new Reference(new XMLSignatureInput(new FileInputStream("1.gif"), |
| * "http://localhost/1.gif", |
| * (Transforms) null, sha1); |
| * Element refElem = ref.toElement(_doc); |
| * </pre> |
| * |
| * <p>Verify a reference</p> |
| * <pre> |
| * Element refElem = _doc.getElement("Reference"); // PSEUDO |
| * Reference ref = new Reference(refElem); |
| * String url = ref.getURI(); |
| * ref.setData(new XMLSignatureInput(new FileInputStream(url))); |
| * if (ref.verify()) { |
| * System.out.println("verified"); |
| * } |
| * </pre> |
| * |
| * <pre> |
| * <element name="Reference" type="ds:ReferenceType"/> |
| * <complexType name="ReferenceType"> |
| * <sequence> |
| * <element ref="ds:Transforms" minOccurs="0"/> |
| * <element ref="ds:DigestMethod"/> |
| * <element ref="ds:DigestValue"/> |
| * </sequence> |
| * <attribute name="Id" type="ID" use="optional"/> |
| * <attribute name="URI" type="anyURI" use="optional"/> |
| * <attribute name="Type" type="anyURI" use="optional"/> |
| * </complexType> |
| * </pre> |
| * |
| * @author Christian Geuer-Pollmann |
| * @see ObjectContainer |
| * @see Manifest |
| */ |
| public class Reference extends SignatureElementProxy { |
| |
| /** |
| * Look up useC14N11 system property. If true, an explicit C14N11 transform |
| * will be added if necessary when generating the signature. See section |
| * 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info. |
| */ |
| private static boolean useC14N11 = |
| AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| public Boolean run() { |
| return Boolean.getBoolean |
| ("com.sun.org.apache.xml.internal.security.useC14N11"); |
| } |
| }); |
| |
| /* |
| static { |
| try { |
| useC14N11 = Boolean.getBoolean("com.sun.org.apache.xml.internal.security.useC14N11"); |
| } catch (Exception e) { |
| // ignore exceptions |
| } |
| } |
| */ |
| |
| /** Field CacheSignedNodes */ |
| public final static boolean CacheSignedNodes = false; |
| |
| /** {@link java.util.logging} logging facility */ |
| static java.util.logging.Logger log = |
| java.util.logging.Logger.getLogger(Reference.class.getName()); |
| |
| /** Field OBJECT_URI */ |
| public static final String OBJECT_URI = Constants.SignatureSpecNS |
| + Constants._TAG_OBJECT; |
| |
| /** Field MANIFEST_URI */ |
| public static final String MANIFEST_URI = Constants.SignatureSpecNS |
| + Constants._TAG_MANIFEST; |
| //J- |
| Manifest _manifest = null; |
| XMLSignatureInput _transformsOutput; |
| //J+ |
| |
| private Transforms transforms; |
| |
| private Element digestMethodElem; |
| |
| private Element digestValueElement; |
| |
| /** |
| * Constructor Reference |
| * |
| * @param doc the {@link Document} in which <code>XMLsignature</code> is placed |
| * @param BaseURI the URI of the resource where the XML instance will be stored |
| * @param ReferenceURI URI indicate where is data which will digested |
| * @param manifest |
| * @param transforms {@link Transforms} applied to data |
| * @param messageDigestAlgorithm {@link MessageDigestAlgorithm Digest algorithm} which is applied to the data |
| * TODO should we throw XMLSignatureException if MessageDigestAlgoURI is wrong? |
| * @throws XMLSignatureException |
| */ |
| protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms, String messageDigestAlgorithm) |
| throws XMLSignatureException { |
| |
| super(doc); |
| |
| XMLUtils.addReturnToElement(this._constructionElement); |
| |
| this._baseURI = BaseURI; |
| this._manifest = manifest; |
| |
| this.setURI(ReferenceURI); |
| |
| // important: The ds:Reference must be added to the associated ds:Manifest |
| // or ds:SignedInfo _before_ the this.resolverResult() is called. |
| // this._manifest.appendChild(this._constructionElement); |
| // this._manifest.appendChild(this._doc.createTextNode("\n")); |
| |
| if (transforms != null) { |
| this.transforms=transforms; |
| this._constructionElement.appendChild(transforms.getElement()); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| { |
| MessageDigestAlgorithm mda = |
| MessageDigestAlgorithm.getInstance(this._doc, |
| messageDigestAlgorithm); |
| |
| digestMethodElem=mda.getElement(); |
| this._constructionElement.appendChild(digestMethodElem); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| { |
| digestValueElement = |
| XMLUtils.createElementInSignatureSpace(this._doc, |
| Constants._TAG_DIGESTVALUE); |
| |
| this._constructionElement.appendChild(digestValueElement); |
| XMLUtils.addReturnToElement(this._constructionElement); |
| } |
| } |
| |
| |
| /** |
| * Build a {@link Reference} from an {@link Element} |
| * |
| * @param element <code>Reference</code> element |
| * @param BaseURI the URI of the resource where the XML instance was stored |
| * @param manifest is the {@link Manifest} of {@link SignedInfo} in which the Reference occurs. We need this because the Manifest has the individual {@link ResourceResolver}s whcih have been set by the user |
| * @throws XMLSecurityException |
| */ |
| protected Reference(Element element, String BaseURI, Manifest manifest) |
| throws XMLSecurityException { |
| |
| super(element, BaseURI); |
| this._baseURI=BaseURI; |
| Element el=XMLUtils.getNextElement(element.getFirstChild()); |
| if (Constants._TAG_TRANSFORMS.equals(el.getLocalName()) && |
| Constants.SignatureSpecNS.equals(el.getNamespaceURI())) { |
| transforms = new Transforms(el,this._baseURI); |
| el=XMLUtils.getNextElement(el.getNextSibling()); |
| } |
| digestMethodElem = el; |
| digestValueElement =XMLUtils.getNextElement(digestMethodElem.getNextSibling());; |
| this._manifest = manifest; |
| } |
| |
| /** |
| * Returns {@link MessageDigestAlgorithm} |
| * |
| * |
| * @return {@link MessageDigestAlgorithm} |
| * |
| * @throws XMLSignatureException |
| */ |
| public MessageDigestAlgorithm getMessageDigestAlgorithm() |
| throws XMLSignatureException { |
| |
| if (digestMethodElem == null) { |
| return null; |
| } |
| |
| String uri = digestMethodElem.getAttributeNS(null, |
| Constants._ATT_ALGORITHM); |
| |
| if (uri == null) { |
| return null; |
| } |
| |
| return MessageDigestAlgorithm.getInstance(this._doc, uri); |
| } |
| |
| /** |
| * Sets the <code>URI</code> of this <code>Reference</code> element |
| * |
| * @param URI the <code>URI</code> of this <code>Reference</code> element |
| */ |
| public void setURI(String URI) { |
| |
| if ( URI != null) { |
| this._constructionElement.setAttributeNS(null, Constants._ATT_URI, |
| URI); |
| } |
| } |
| |
| /** |
| * Returns the <code>URI</code> of this <code>Reference</code> element |
| * |
| * @return URI the <code>URI</code> of this <code>Reference</code> element |
| */ |
| public String getURI() { |
| return this._constructionElement.getAttributeNS(null, Constants._ATT_URI); |
| } |
| |
| /** |
| * Sets the <code>Id</code> attribute of this <code>Reference</code> element |
| * |
| * @param Id the <code>Id</code> attribute of this <code>Reference</code> element |
| */ |
| public void setId(String Id) { |
| |
| if ( Id != null ) { |
| setLocalIdAttribute(Constants._ATT_ID, Id); |
| } |
| } |
| |
| /** |
| * Returns the <code>Id</code> attribute of this <code>Reference</code> element |
| * |
| * @return Id the <code>Id</code> attribute of this <code>Reference</code> element |
| */ |
| public String getId() { |
| return this._constructionElement.getAttributeNS(null, Constants._ATT_ID); |
| } |
| |
| /** |
| * Sets the <code>type</code> atttibute of the Reference indicate whether an <code>ds:Object</code>, <code>ds:SignatureProperty</code>, or <code>ds:Manifest</code> element |
| * |
| * @param Type the <code>type</code> attribute of the Reference |
| */ |
| public void setType(String Type) { |
| |
| if (Type != null) { |
| this._constructionElement.setAttributeNS(null, Constants._ATT_TYPE, |
| Type); |
| } |
| } |
| |
| /** |
| * Return the <code>type</code> atttibute of the Reference indicate whether an <code>ds:Object</code>, <code>ds:SignatureProperty</code>, or <code>ds:Manifest</code> element |
| * |
| * @return the <code>type</code> attribute of the Reference |
| */ |
| public String getType() { |
| return this._constructionElement.getAttributeNS(null, |
| Constants._ATT_TYPE); |
| } |
| |
| /** |
| * Method isReferenceToObject |
| * |
| * This returns true if the <CODE>Type</CODE> attribute of the |
| * <CODE>Refernce</CODE> element points to a <CODE>#Object</CODE> element |
| * |
| * @return true if the Reference type indicates that this Reference points to an <code>Object</code> |
| */ |
| public boolean typeIsReferenceToObject() { |
| |
| if (Reference.OBJECT_URI.equals(this.getType())) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Method isReferenceToManifest |
| * |
| * This returns true if the <CODE>Type</CODE> attribute of the |
| * <CODE>Refernce</CODE> element points to a <CODE>#Manifest</CODE> element |
| * |
| * @return true if the Reference type indicates that this Reference points to a {@link Manifest} |
| */ |
| public boolean typeIsReferenceToManifest() { |
| |
| if (Reference.MANIFEST_URI.equals(this.getType())) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Method setDigestValueElement |
| * |
| * @param digestValue |
| */ |
| private void setDigestValueElement(byte[] digestValue) |
| { |
| Node n=digestValueElement.getFirstChild(); |
| while (n!=null) { |
| digestValueElement.removeChild(n); |
| n = n.getNextSibling(); |
| } |
| |
| String base64codedValue = Base64.encode(digestValue); |
| Text t = this._doc.createTextNode(base64codedValue); |
| |
| digestValueElement.appendChild(t); |
| } |
| |
| /** |
| * Method generateDigestValue |
| * |
| * @throws ReferenceNotInitializedException |
| * @throws XMLSignatureException |
| */ |
| public void generateDigestValue() |
| throws XMLSignatureException, ReferenceNotInitializedException { |
| this.setDigestValueElement(this.calculateDigest(false)); |
| } |
| |
| /** |
| * Returns the XMLSignatureInput which is created by de-referencing the URI attribute. |
| * @return the XMLSignatureInput of the source of this reference |
| * @throws ReferenceNotInitializedException If the resolver found any |
| * problem resolving the reference |
| */ |
| public XMLSignatureInput getContentsBeforeTransformation() |
| throws ReferenceNotInitializedException { |
| |
| try { |
| Attr URIAttr = this._constructionElement.getAttributeNodeNS(null, |
| Constants._ATT_URI); |
| String URI; |
| |
| if (URIAttr == null) { |
| URI = null; |
| } else { |
| URI = URIAttr.getNodeValue(); |
| } |
| |
| ResourceResolver resolver = ResourceResolver.getInstance(URIAttr, |
| this._baseURI, this._manifest._perManifestResolvers); |
| |
| if (resolver == null) { |
| Object exArgs[] = { URI }; |
| |
| throw new ReferenceNotInitializedException( |
| "signature.Verification.Reference.NoInput", exArgs); |
| } |
| |
| resolver.addProperties(this._manifest._resolverProperties); |
| |
| XMLSignatureInput input = resolver.resolve(URIAttr, this._baseURI); |
| |
| |
| return input; |
| } catch (ResourceResolverException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } catch (XMLSecurityException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } |
| } |
| |
| /** |
| * Returns the data which is referenced by the URI attribute. This method |
| * only works works after a call to verify. |
| * @return a XMLSignature with a byte array. |
| * @throws ReferenceNotInitializedException |
| * |
| * @deprecated use getContentsBeforeTransformation |
| */ |
| public XMLSignatureInput getTransformsInput() throws ReferenceNotInitializedException |
| { |
| XMLSignatureInput input=getContentsBeforeTransformation(); |
| XMLSignatureInput result; |
| try { |
| result = new XMLSignatureInput(input.getBytes()); |
| } catch (CanonicalizationException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } catch (IOException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } |
| result.setSourceURI(input.getSourceURI()); |
| return result; |
| |
| } |
| |
| private XMLSignatureInput getContentsAfterTransformation(XMLSignatureInput input, OutputStream os) |
| throws XMLSignatureException { |
| |
| try { |
| Transforms transforms = this.getTransforms(); |
| XMLSignatureInput output = null; |
| |
| if (transforms != null) { |
| output = transforms.performTransforms(input,os); |
| this._transformsOutput = output;//new XMLSignatureInput(output.getBytes()); |
| |
| //this._transformsOutput.setSourceURI(output.getSourceURI()); |
| } else { |
| output = input; |
| } |
| |
| return output; |
| } catch (ResourceResolverException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (CanonicalizationException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (InvalidCanonicalizerException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (TransformationException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (XMLSecurityException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } |
| } |
| |
| /** |
| * Returns the XMLSignatureInput which is the result of the Transforms. |
| * @return a XMLSignatureInput with all transformations applied. |
| * @throws XMLSignatureException |
| */ |
| public XMLSignatureInput getContentsAfterTransformation() |
| throws XMLSignatureException { |
| |
| XMLSignatureInput input = this.getContentsBeforeTransformation(); |
| |
| return this.getContentsAfterTransformation(input, null); |
| } |
| |
| /** |
| * This method returns the XMLSignatureInput which represents the node set before |
| * some kind of canonicalization is applied for the first time. |
| * @return Gets a the node doing everything till the first c14n is needed |
| * |
| * @throws XMLSignatureException |
| */ |
| public XMLSignatureInput getNodesetBeforeFirstCanonicalization() |
| throws XMLSignatureException { |
| |
| try { |
| XMLSignatureInput input = this.getContentsBeforeTransformation(); |
| XMLSignatureInput output = input; |
| Transforms transforms = this.getTransforms(); |
| |
| if (transforms != null) { |
| doTransforms: for (int i = 0; i < transforms.getLength(); i++) { |
| Transform t = transforms.item(i); |
| String URI = t.getURI(); |
| |
| if (URI.equals(Transforms |
| .TRANSFORM_C14N_EXCL_OMIT_COMMENTS) || URI |
| .equals(Transforms |
| .TRANSFORM_C14N_EXCL_WITH_COMMENTS) || URI |
| .equals(Transforms |
| .TRANSFORM_C14N_OMIT_COMMENTS) || URI |
| .equals(Transforms |
| .TRANSFORM_C14N_WITH_COMMENTS)) { |
| |
| break doTransforms; |
| } |
| |
| output = t.performTransform(output, null); |
| } |
| |
| output.setSourceURI(input.getSourceURI()); |
| } |
| return output; |
| } catch (IOException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (ResourceResolverException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (CanonicalizationException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (InvalidCanonicalizerException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (TransformationException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (XMLSecurityException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } |
| } |
| |
| /** |
| * Method getHTMLRepresentation |
| * @return The HTML of the transformation |
| * @throws XMLSignatureException |
| */ |
| public String getHTMLRepresentation() throws XMLSignatureException { |
| |
| try { |
| XMLSignatureInput nodes = this.getNodesetBeforeFirstCanonicalization(); |
| Set inclusiveNamespaces = new HashSet(); |
| |
| { |
| Transforms transforms = this.getTransforms(); |
| Transform c14nTransform = null; |
| |
| if (transforms != null) { |
| doTransforms: for (int i = 0; i < transforms.getLength(); i++) { |
| Transform t = transforms.item(i); |
| String URI = t.getURI(); |
| |
| if (URI.equals(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS) |
| || URI.equals( |
| Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS)) { |
| c14nTransform = t; |
| |
| break doTransforms; |
| } |
| } |
| } |
| |
| if (c14nTransform != null) { |
| |
| if (c14nTransform |
| .length(InclusiveNamespaces |
| .ExclusiveCanonicalizationNamespace, InclusiveNamespaces |
| ._TAG_EC_INCLUSIVENAMESPACES) == 1) { |
| |
| // there is one InclusiveNamespaces element |
| InclusiveNamespaces in = new InclusiveNamespaces( |
| XMLUtils.selectNode( |
| c14nTransform.getElement().getFirstChild(), |
| InclusiveNamespaces.ExclusiveCanonicalizationNamespace, |
| InclusiveNamespaces._TAG_EC_INCLUSIVENAMESPACES,0), this.getBaseURI()); |
| |
| inclusiveNamespaces = InclusiveNamespaces.prefixStr2Set( |
| in.getInclusiveNamespaces()); |
| } |
| } |
| } |
| |
| return nodes.getHTMLRepresentation(inclusiveNamespaces); |
| } catch (TransformationException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (InvalidTransformException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } catch (XMLSecurityException ex) { |
| throw new XMLSignatureException("empty", ex); |
| } |
| } |
| |
| /** |
| * This method only works works after a call to verify. |
| * @return the transformed output(i.e. what is going to be digested). |
| */ |
| public XMLSignatureInput getTransformsOutput() { |
| return this._transformsOutput; |
| } |
| |
| /** |
| * This method returns the {@link XMLSignatureInput} which is referenced by the |
| * <CODE>URI</CODE> Attribute. |
| * @param os where to write the transformation can be null. |
| * @return the element to digest |
| * |
| * @throws XMLSignatureException |
| * @see Manifest#verifyReferences() |
| */ |
| protected XMLSignatureInput dereferenceURIandPerformTransforms(OutputStream os) |
| throws XMLSignatureException { |
| |
| try { |
| XMLSignatureInput input = this.getContentsBeforeTransformation(); |
| XMLSignatureInput output = this.getContentsAfterTransformation(input, os); |
| |
| /* at this stage, this._transformsInput and this._transformsOutput |
| * contain a huge amount of nodes. When we do not cache these nodes |
| * but only preserve the octets, the memory footprint is dramatically |
| * reduced. |
| */ |
| if (!Reference.CacheSignedNodes) { |
| |
| this._transformsOutput = output;//new XMLSignatureInput(output.getBytes()); |
| |
| //this._transformsOutput.setSourceURI(output.getSourceURI()); |
| } |
| return output; |
| } catch (XMLSecurityException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } |
| } |
| |
| /** |
| * Method getTransforms |
| * |
| * @return The transforms that applied this reference. |
| * @throws InvalidTransformException |
| * @throws TransformationException |
| * @throws XMLSecurityException |
| * @throws XMLSignatureException |
| */ |
| public Transforms getTransforms() |
| throws XMLSignatureException, InvalidTransformException, |
| TransformationException, XMLSecurityException { |
| |
| return transforms; |
| } |
| |
| /** |
| * Method getReferencedBytes |
| * |
| * @return the bytes that will be used to generated digest. |
| * @throws ReferenceNotInitializedException |
| * @throws XMLSignatureException |
| */ |
| public byte[] getReferencedBytes() |
| throws ReferenceNotInitializedException, XMLSignatureException { |
| try { |
| XMLSignatureInput output=this.dereferenceURIandPerformTransforms(null); |
| |
| byte[] signedBytes = output.getBytes(); |
| |
| return signedBytes; |
| } catch (IOException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } catch (CanonicalizationException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } |
| |
| } |
| |
| |
| /** |
| * Method calculateDigest |
| * |
| * @param validating true if validating the reference |
| * @return reference Calculate the digest of this reference. |
| * @throws ReferenceNotInitializedException |
| * @throws XMLSignatureException |
| */ |
| private byte[] calculateDigest(boolean validating) |
| throws ReferenceNotInitializedException, XMLSignatureException { |
| |
| try { |
| |
| MessageDigestAlgorithm mda = this.getMessageDigestAlgorithm(); |
| |
| mda.reset(); |
| DigesterOutputStream diOs=new DigesterOutputStream(mda); |
| OutputStream os=new UnsyncBufferedOutputStream(diOs); |
| XMLSignatureInput output=this.dereferenceURIandPerformTransforms(os); |
| // if signing and c14n11 property == true explicitly add |
| // C14N11 transform if needed |
| if (this.useC14N11 && !validating && |
| !output.isOutputStreamSet() && !output.isOctetStream()) { |
| if (transforms == null) { |
| transforms = new Transforms(this._doc); |
| this._constructionElement.insertBefore |
| (transforms.getElement(), digestMethodElem); |
| } |
| transforms.addTransform(Transforms.TRANSFORM_C14N11_OMIT_COMMENTS); |
| output.updateOutputStream(os, true); |
| } else { |
| output.updateOutputStream(os); |
| } |
| os.flush(); |
| //this.getReferencedBytes(diOs); |
| //mda.update(data); |
| |
| return diOs.getDigestValue(); |
| } catch (XMLSecurityException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } catch (IOException ex) { |
| throw new ReferenceNotInitializedException("empty", ex); |
| } |
| } |
| |
| /** |
| * Returns the digest value. |
| * |
| * @return the digest value. |
| * @throws Base64DecodingException if Reference contains no proper base64 encoded data. |
| * @throws XMLSecurityException if the Reference does not contain a DigestValue element |
| */ |
| public byte[] getDigestValue() throws Base64DecodingException, XMLSecurityException { |
| if (digestValueElement == null) { |
| // The required element is not in the XML! |
| Object[] exArgs ={ Constants._TAG_DIGESTVALUE, |
| Constants.SignatureSpecNS }; |
| throw new XMLSecurityException( |
| "signature.Verification.NoSignatureElement", |
| exArgs); |
| } |
| byte[] elemDig = Base64.decode(digestValueElement); |
| return elemDig; |
| } |
| |
| |
| /** |
| * Tests reference valdiation is success or false |
| * |
| * @return true if reference valdiation is success, otherwise false |
| * @throws ReferenceNotInitializedException |
| * @throws XMLSecurityException |
| */ |
| public boolean verify() |
| throws ReferenceNotInitializedException, XMLSecurityException { |
| |
| byte[] elemDig = this.getDigestValue(); |
| byte[] calcDig = this.calculateDigest(true); |
| boolean equal = MessageDigestAlgorithm.isEqual(elemDig, calcDig); |
| |
| if (!equal) { |
| log.log(java.util.logging.Level.WARNING, "Verification failed for URI \"" + this.getURI() + "\""); |
| log.log(java.util.logging.Level.WARNING, "Expected Digest: " + Base64.encode(elemDig)); |
| log.log(java.util.logging.Level.WARNING, "Actual Digest: " + Base64.encode(calcDig)); |
| } else { |
| log.log(java.util.logging.Level.INFO, "Verification successful for URI \"" + this.getURI() + "\""); |
| } |
| |
| return equal; |
| } |
| |
| /** |
| * Method getBaseLocalName |
| * @inheritDoc |
| * |
| */ |
| public String getBaseLocalName() { |
| return Constants._TAG_REFERENCE; |
| } |
| } |