jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java
changeset 18780 f47b920867e7
parent 18240 cda839ac048f
child 19051 6c0cfc00b3ed
equal deleted inserted replaced
18534:2d131cf5db63 18780:f47b920867e7
     1 /*
     1 /*
     2  * reserved comment block
     2  * reserved comment block
     3  * DO NOT REMOVE OR ALTER!
     3  * DO NOT REMOVE OR ALTER!
     4  */
     4  */
     5 /*
     5 /**
     6  * Copyright 2005 The Apache Software Foundation.
     6  * Licensed to the Apache Software Foundation (ASF) under one
       
     7  * or more contributor license agreements. See the NOTICE file
       
     8  * distributed with this work for additional information
       
     9  * regarding copyright ownership. The ASF licenses this file
       
    10  * to you under the Apache License, Version 2.0 (the
       
    11  * "License"); you may not use this file except in compliance
       
    12  * with the License. You may obtain a copy of the License at
     7  *
    13  *
     8  *  Licensed under the Apache License, Version 2.0 (the "License");
    14  * http://www.apache.org/licenses/LICENSE-2.0
     9  *  you may not use this file except in compliance with the License.
       
    10  *  You may obtain a copy of the License at
       
    11  *
    15  *
    12  *      http://www.apache.org/licenses/LICENSE-2.0
    16  * Unless required by applicable law or agreed to in writing,
    13  *
    17  * software distributed under the License is distributed on an
    14  *  Unless required by applicable law or agreed to in writing, software
    18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15  *  distributed under the License is distributed on an "AS IS" BASIS,
    19  * KIND, either express or implied. See the License for the
    16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20  * specific language governing permissions and limitations
    17  *  See the License for the specific language governing permissions and
    21  * under the License.
    18  *  limitations under the License.
       
    19  *
       
    20  */
    22  */
    21 /*
    23 /*
    22  * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
    24  * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
    23  */
    25  */
    24 /*
    26 /*
    27  * (C) Copyright IBM Corp. 2003 All Rights Reserved.
    29  * (C) Copyright IBM Corp. 2003 All Rights Reserved.
    28  *
    30  *
    29  * ===========================================================================
    31  * ===========================================================================
    30  */
    32  */
    31 /*
    33 /*
    32  * $Id: DOMXMLSignature.java,v 1.2 2008/07/24 15:20:32 mullan Exp $
    34  * $Id: DOMXMLSignature.java 1333415 2012-05-03 12:03:51Z coheigea $
    33  */
    35  */
    34 package org.jcp.xml.dsig.internal.dom;
    36 package org.jcp.xml.dsig.internal.dom;
    35 
    37 
    36 import javax.xml.crypto.*;
    38 import javax.xml.crypto.*;
    37 import javax.xml.crypto.dom.*;
    39 import javax.xml.crypto.dom.*;
    38 import javax.xml.crypto.dsig.*;
    40 import javax.xml.crypto.dsig.*;
    39 import javax.xml.crypto.dsig.dom.DOMSignContext;
    41 import javax.xml.crypto.dsig.dom.DOMSignContext;
    40 import javax.xml.crypto.dsig.dom.DOMValidateContext;
    42 import javax.xml.crypto.dsig.dom.DOMValidateContext;
    41 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
    43 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
    42 
    44 
    43 import java.io.*;
       
    44 import java.security.InvalidKeyException;
    45 import java.security.InvalidKeyException;
    45 import java.security.Key;
    46 import java.security.Key;
    46 import java.security.Provider;
    47 import java.security.Provider;
    47 import java.util.Collections;
    48 import java.util.Collections;
    48 import java.util.ArrayList;
    49 import java.util.ArrayList;
    49 import java.util.HashMap;
    50 import java.util.HashMap;
    50 import java.util.List;
    51 import java.util.List;
    51 import java.util.logging.Level;
    52 
    52 import java.util.logging.Logger;
       
    53 import org.w3c.dom.Attr;
    53 import org.w3c.dom.Attr;
    54 import org.w3c.dom.Document;
    54 import org.w3c.dom.Document;
    55 import org.w3c.dom.Element;
    55 import org.w3c.dom.Element;
    56 import org.w3c.dom.Node;
    56 import org.w3c.dom.Node;
    57 
    57 
    65  * @author Joyce Leung
    65  * @author Joyce Leung
    66  */
    66  */
    67 public final class DOMXMLSignature extends DOMStructure
    67 public final class DOMXMLSignature extends DOMStructure
    68     implements XMLSignature {
    68     implements XMLSignature {
    69 
    69 
    70     private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom");
    70     private static java.util.logging.Logger log =
       
    71         java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
    71     private String id;
    72     private String id;
    72     private SignatureValue sv;
    73     private SignatureValue sv;
    73     private KeyInfo ki;
    74     private KeyInfo ki;
    74     private List objects;
    75     private List<XMLObject> objects;
    75     private SignedInfo si;
    76     private SignedInfo si;
    76     private Document ownerDoc = null;
    77     private Document ownerDoc = null;
    77     private Element localSigElem = null;
    78     private Element localSigElem = null;
    78     private Element sigElem = null;
    79     private Element sigElem = null;
    79     private boolean validationStatus;
    80     private boolean validationStatus;
    80     private boolean validated = false;
    81     private boolean validated = false;
    81     private KeySelectorResult ksr;
    82     private KeySelectorResult ksr;
    82     private HashMap signatureIdMap;
    83     private HashMap<String, XMLStructure> signatureIdMap;
    83 
    84 
    84     static {
    85     static {
    85         com.sun.org.apache.xml.internal.security.Init.init();
    86         com.sun.org.apache.xml.internal.security.Init.init();
    86     }
    87     }
    87 
    88 
    96      * @param id an optional id (specify <code>null</code> to omit)
    97      * @param id an optional id (specify <code>null</code> to omit)
    97      * @param signatureValueId an optional id (specify <code>null</code> to
    98      * @param signatureValueId an optional id (specify <code>null</code> to
    98      *  omit)
    99      *  omit)
    99      * @throws NullPointerException if <code>si</code> is <code>null</code>
   100      * @throws NullPointerException if <code>si</code> is <code>null</code>
   100      */
   101      */
   101     public DOMXMLSignature(SignedInfo si, KeyInfo ki, List objs, String id,
   102     public DOMXMLSignature(SignedInfo si, KeyInfo ki,
   102         String signatureValueId)
   103                            List<? extends XMLObject> objs,
       
   104                            String id, String signatureValueId)
   103     {
   105     {
   104         if (si == null) {
   106         if (si == null) {
   105             throw new NullPointerException("signedInfo cannot be null");
   107             throw new NullPointerException("signedInfo cannot be null");
   106         }
   108         }
   107         this.si = si;
   109         this.si = si;
   108         this.id = id;
   110         this.id = id;
   109         this.sv = new DOMSignatureValue(signatureValueId);
   111         this.sv = new DOMSignatureValue(signatureValueId);
   110         if (objs == null) {
   112         if (objs == null) {
   111             this.objects = Collections.EMPTY_LIST;
   113             this.objects = Collections.emptyList();
   112         } else {
   114         } else {
   113             List objsCopy = new ArrayList(objs);
   115             this.objects =
   114             for (int i = 0, size = objsCopy.size(); i < size; i++) {
   116                 Collections.unmodifiableList(new ArrayList<XMLObject>(objs));
   115                 if (!(objsCopy.get(i) instanceof XMLObject)) {
   117             for (int i = 0, size = this.objects.size(); i < size; i++) {
       
   118                 if (!(this.objects.get(i) instanceof XMLObject)) {
   116                     throw new ClassCastException
   119                     throw new ClassCastException
   117                         ("objs["+i+"] is not an XMLObject");
   120                         ("objs["+i+"] is not an XMLObject");
   118                 }
   121                 }
   119             }
   122             }
   120             this.objects = Collections.unmodifiableList(objsCopy);
       
   121         }
   123         }
   122         this.ki = ki;
   124         this.ki = ki;
   123     }
   125     }
   124 
   126 
   125     /**
   127     /**
   127      *
   129      *
   128      * @param sigElem Signature element
   130      * @param sigElem Signature element
   129      * @throws MarshalException if XMLSignature cannot be unmarshalled
   131      * @throws MarshalException if XMLSignature cannot be unmarshalled
   130      */
   132      */
   131     public DOMXMLSignature(Element sigElem, XMLCryptoContext context,
   133     public DOMXMLSignature(Element sigElem, XMLCryptoContext context,
   132         Provider provider) throws MarshalException {
   134                            Provider provider)
       
   135         throws MarshalException
       
   136     {
   133         localSigElem = sigElem;
   137         localSigElem = sigElem;
   134         ownerDoc = localSigElem.getOwnerDocument();
   138         ownerDoc = localSigElem.getOwnerDocument();
   135 
   139 
   136         // get Id attribute, if specified
   140         // get Id attribute, if specified
   137         id = DOMUtils.getAttributeValue(localSigElem, "Id");
   141         id = DOMUtils.getAttributeValue(localSigElem, "Id");
   140         Element siElem = DOMUtils.getFirstChildElement(localSigElem);
   144         Element siElem = DOMUtils.getFirstChildElement(localSigElem);
   141         si = new DOMSignedInfo(siElem, context, provider);
   145         si = new DOMSignedInfo(siElem, context, provider);
   142 
   146 
   143         // unmarshal SignatureValue
   147         // unmarshal SignatureValue
   144         Element sigValElem = DOMUtils.getNextSiblingElement(siElem);
   148         Element sigValElem = DOMUtils.getNextSiblingElement(siElem);
   145         sv = new DOMSignatureValue(sigValElem);
   149         sv = new DOMSignatureValue(sigValElem, context);
   146 
   150 
   147         // unmarshal KeyInfo, if specified
   151         // unmarshal KeyInfo, if specified
   148         Element nextSibling = DOMUtils.getNextSiblingElement(sigValElem);
   152         Element nextSibling = DOMUtils.getNextSiblingElement(sigValElem);
   149         if (nextSibling != null && nextSibling.getLocalName().equals("KeyInfo")) {
   153         if (nextSibling != null && nextSibling.getLocalName().equals("KeyInfo")) {
   150             ki = new DOMKeyInfo(nextSibling, context, provider);
   154             ki = new DOMKeyInfo(nextSibling, context, provider);
   151             nextSibling = DOMUtils.getNextSiblingElement(nextSibling);
   155             nextSibling = DOMUtils.getNextSiblingElement(nextSibling);
   152         }
   156         }
   153 
   157 
   154         // unmarshal Objects, if specified
   158         // unmarshal Objects, if specified
   155         if (nextSibling == null) {
   159         if (nextSibling == null) {
   156             objects = Collections.EMPTY_LIST;
   160             objects = Collections.emptyList();
   157         } else {
   161         } else {
   158             List tempObjects = new ArrayList();
   162             List<XMLObject> tempObjects = new ArrayList<XMLObject>();
   159             while (nextSibling != null) {
   163             while (nextSibling != null) {
   160                 tempObjects.add
   164                 tempObjects.add(new DOMXMLObject(nextSibling,
   161                     (new DOMXMLObject(nextSibling, context, provider));
   165                                                  context, provider));
   162                 nextSibling = DOMUtils.getNextSiblingElement(nextSibling);
   166                 nextSibling = DOMUtils.getNextSiblingElement(nextSibling);
   163             }
   167             }
   164             objects = Collections.unmodifiableList(tempObjects);
   168             objects = Collections.unmodifiableList(tempObjects);
   165         }
   169         }
   166     }
   170     }
   188     public KeySelectorResult getKeySelectorResult() {
   192     public KeySelectorResult getKeySelectorResult() {
   189         return ksr;
   193         return ksr;
   190     }
   194     }
   191 
   195 
   192     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
   196     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
   193         throws MarshalException {
   197         throws MarshalException
       
   198     {
   194         marshal(parent, null, dsPrefix, context);
   199         marshal(parent, null, dsPrefix, context);
   195     }
   200     }
   196 
   201 
   197     public void marshal(Node parent, Node nextSibling, String dsPrefix,
   202     public void marshal(Node parent, Node nextSibling, String dsPrefix,
   198         DOMCryptoContext context) throws MarshalException {
   203                         DOMCryptoContext context)
       
   204         throws MarshalException
       
   205     {
   199         ownerDoc = DOMUtils.getOwnerDocument(parent);
   206         ownerDoc = DOMUtils.getOwnerDocument(parent);
   200 
   207         sigElem = DOMUtils.createElement(ownerDoc, "Signature",
   201         sigElem = DOMUtils.createElement
   208                                          XMLSignature.XMLNS, dsPrefix);
   202             (ownerDoc, "Signature", XMLSignature.XMLNS, dsPrefix);
       
   203 
   209 
   204         // append xmlns attribute
   210         // append xmlns attribute
   205         if (dsPrefix == null || dsPrefix.length() == 0) {
   211         if (dsPrefix == null || dsPrefix.length() == 0) {
   206             sigElem.setAttributeNS
   212             sigElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns",
   207                 ("http://www.w3.org/2000/xmlns/", "xmlns", XMLSignature.XMLNS);
   213                                    XMLSignature.XMLNS);
   208         } else {
   214         } else {
   209             sigElem.setAttributeNS
   215             sigElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" +
   210                 ("http://www.w3.org/2000/xmlns/", "xmlns:" + dsPrefix,
   216                                    dsPrefix, XMLSignature.XMLNS);
   211                  XMLSignature.XMLNS);
       
   212         }
   217         }
   213 
   218 
   214         // create and append SignedInfo element
   219         // create and append SignedInfo element
   215         ((DOMSignedInfo) si).marshal(sigElem, dsPrefix, context);
   220         ((DOMSignedInfo)si).marshal(sigElem, dsPrefix, context);
   216 
   221 
   217         // create and append SignatureValue element
   222         // create and append SignatureValue element
   218         ((DOMSignatureValue) sv).marshal(sigElem, dsPrefix, context);
   223         ((DOMSignatureValue)sv).marshal(sigElem, dsPrefix, context);
   219 
   224 
   220         // create and append KeyInfo element if necessary
   225         // create and append KeyInfo element if necessary
   221         if (ki != null) {
   226         if (ki != null) {
   222             ((DOMKeyInfo) ki).marshal(sigElem, null, dsPrefix, context);
   227             ((DOMKeyInfo)ki).marshal(sigElem, null, dsPrefix, context);
   223         }
   228         }
   224 
   229 
   225         // create and append Object elements if necessary
   230         // create and append Object elements if necessary
   226         for (int i = 0, size = objects.size(); i < size; i++) {
   231         for (int i = 0, size = objects.size(); i < size; i++) {
   227             ((DOMXMLObject) objects.get(i)).marshal(sigElem, dsPrefix, context);
   232             ((DOMXMLObject)objects.get(i)).marshal(sigElem, dsPrefix, context);
   228         }
   233         }
   229 
   234 
   230         // append Id attribute
   235         // append Id attribute
   231         DOMUtils.setAttributeID(sigElem, "Id", id);
   236         DOMUtils.setAttributeID(sigElem, "Id", id);
   232 
   237 
   233         parent.insertBefore(sigElem, nextSibling);
   238         parent.insertBefore(sigElem, nextSibling);
   234     }
   239     }
   235 
   240 
   236     public boolean validate(XMLValidateContext vc)
   241     public boolean validate(XMLValidateContext vc)
   237         throws XMLSignatureException {
   242         throws XMLSignatureException
   238 
   243     {
   239         if (vc == null) {
   244         if (vc == null) {
   240             throw new NullPointerException("validateContext is null");
   245             throw new NullPointerException("validateContext is null");
   241         }
   246         }
   242 
   247 
   243         if (!(vc instanceof DOMValidateContext)) {
   248         if (!(vc instanceof DOMValidateContext)) {
   256             validated = true;
   261             validated = true;
   257             return validationStatus;
   262             return validationStatus;
   258         }
   263         }
   259 
   264 
   260         // validate all References
   265         // validate all References
   261         List refs = this.si.getReferences();
   266         @SuppressWarnings("unchecked")
       
   267         List<Reference> refs = this.si.getReferences();
   262         boolean validateRefs = true;
   268         boolean validateRefs = true;
   263         for (int i = 0, size = refs.size(); validateRefs && i < size; i++) {
   269         for (int i = 0, size = refs.size(); validateRefs && i < size; i++) {
   264             Reference ref = (Reference) refs.get(i);
   270             Reference ref = refs.get(i);
   265             boolean refValid = ref.validate(vc);
   271             boolean refValid = ref.validate(vc);
   266             if (log.isLoggable(Level.FINE)) {
   272             if (log.isLoggable(java.util.logging.Level.FINE)) {
   267                 log.log(Level.FINE, "Reference[" + ref.getURI() + "] is valid: "
   273                 log.log(java.util.logging.Level.FINE, "Reference[" + ref.getURI() + "] is valid: " + refValid);
   268                     + refValid);
       
   269             }
   274             }
   270             validateRefs &= refValid;
   275             validateRefs &= refValid;
   271         }
   276         }
   272         if (!validateRefs) {
   277         if (!validateRefs) {
   273             if (log.isLoggable(Level.FINE)) {
   278             if (log.isLoggable(java.util.logging.Level.FINE)) {
   274                 log.log(Level.FINE, "Couldn't validate the References");
   279                 log.log(java.util.logging.Level.FINE, "Couldn't validate the References");
   275             }
   280             }
   276             validationStatus = false;
   281             validationStatus = false;
   277             validated = true;
   282             validated = true;
   278             return validationStatus;
   283             return validationStatus;
   279         }
   284         }
   280 
   285 
   281         // validate Manifests, if property set
   286         // validate Manifests, if property set
   282         boolean validateMans = true;
   287         boolean validateMans = true;
   283         if (Boolean.TRUE.equals(vc.getProperty
   288         if (Boolean.TRUE.equals(vc.getProperty
   284             ("org.jcp.xml.dsig.validateManifests"))) {
   289                                 ("org.jcp.xml.dsig.validateManifests")))
   285 
   290         {
   286             for (int i=0, size=objects.size(); validateMans && i < size; i++) {
   291             for (int i=0, size=objects.size(); validateMans && i < size; i++) {
   287                 XMLObject xo = (XMLObject) objects.get(i);
   292                 XMLObject xo = objects.get(i);
   288                 List content = xo.getContent();
   293                 @SuppressWarnings("unchecked")
       
   294                 List<XMLStructure> content = xo.getContent();
   289                 int csize = content.size();
   295                 int csize = content.size();
   290                 for (int j = 0; validateMans && j < csize; j++) {
   296                 for (int j = 0; validateMans && j < csize; j++) {
   291                     XMLStructure xs = (XMLStructure) content.get(j);
   297                     XMLStructure xs = content.get(j);
   292                     if (xs instanceof Manifest) {
   298                     if (xs instanceof Manifest) {
   293                         if (log.isLoggable(Level.FINE)) {
   299                         if (log.isLoggable(java.util.logging.Level.FINE)) {
   294                             log.log(Level.FINE, "validating manifest");
   300                             log.log(java.util.logging.Level.FINE, "validating manifest");
   295                         }
   301                         }
   296                         Manifest man = (Manifest) xs;
   302                         Manifest man = (Manifest)xs;
   297                         List manRefs = man.getReferences();
   303                         @SuppressWarnings("unchecked")
       
   304                         List<Reference> manRefs = man.getReferences();
   298                         int rsize = manRefs.size();
   305                         int rsize = manRefs.size();
   299                         for (int k = 0; validateMans && k < rsize; k++) {
   306                         for (int k = 0; validateMans && k < rsize; k++) {
   300                             Reference ref = (Reference) manRefs.get(k);
   307                             Reference ref = manRefs.get(k);
   301                             boolean refValid = ref.validate(vc);
   308                             boolean refValid = ref.validate(vc);
   302                             if (log.isLoggable(Level.FINE)) {
   309                             if (log.isLoggable(java.util.logging.Level.FINE)) {
   303                                 log.log(Level.FINE, "Manifest ref["
   310                                 log.log(java.util.logging.Level.FINE,
   304                                     + ref.getURI() + "] is valid: " + refValid);
   311                                     "Manifest ref[" + ref.getURI() + "] is valid: " + refValid
       
   312                                 );
   305                             }
   313                             }
   306                             validateMans &= refValid;
   314                             validateMans &= refValid;
   307                         }
   315                         }
   308                     }
   316                     }
   309                 }
   317                 }
   314         validated = true;
   322         validated = true;
   315         return validationStatus;
   323         return validationStatus;
   316     }
   324     }
   317 
   325 
   318     public void sign(XMLSignContext signContext)
   326     public void sign(XMLSignContext signContext)
   319         throws MarshalException, XMLSignatureException {
   327         throws MarshalException, XMLSignatureException
       
   328     {
   320         if (signContext == null) {
   329         if (signContext == null) {
   321             throw new NullPointerException("signContext cannot be null");
   330             throw new NullPointerException("signContext cannot be null");
   322         }
   331         }
   323         DOMSignContext context = (DOMSignContext) signContext;
   332         DOMSignContext context = (DOMSignContext)signContext;
   324         if (context != null) {
   333         marshal(context.getParent(), context.getNextSibling(),
   325             marshal(context.getParent(), context.getNextSibling(),
       
   326                 DOMUtils.getSignaturePrefix(context), context);
   334                 DOMUtils.getSignaturePrefix(context), context);
   327         }
       
   328 
   335 
   329         // generate references and signature value
   336         // generate references and signature value
   330         List allReferences = new ArrayList();
   337         List<Reference> allReferences = new ArrayList<Reference>();
   331 
   338 
   332         // traverse the Signature and register all objects with IDs that
   339         // traverse the Signature and register all objects with IDs that
   333         // may contain References
   340         // may contain References
   334         signatureIdMap = new HashMap();
   341         signatureIdMap = new HashMap<String, XMLStructure>();
   335         signatureIdMap.put(id, this);
   342         signatureIdMap.put(id, this);
   336         signatureIdMap.put(si.getId(), si);
   343         signatureIdMap.put(si.getId(), si);
   337         List refs = si.getReferences();
   344         @SuppressWarnings("unchecked")
   338         for (int i = 0, size = refs.size(); i < size; i++) {
   345         List<Reference> refs = si.getReferences();
   339             Reference ref = (Reference) refs.get(i);
   346         for (Reference ref : refs) {
   340             signatureIdMap.put(ref.getId(), ref);
   347             signatureIdMap.put(ref.getId(), ref);
   341         }
   348         }
   342         for (int i = 0, size = objects.size(); i < size; i++) {
   349         for (XMLObject obj : objects) {
   343             XMLObject obj = (XMLObject) objects.get(i);
       
   344             signatureIdMap.put(obj.getId(), obj);
   350             signatureIdMap.put(obj.getId(), obj);
   345             List content = obj.getContent();
   351             @SuppressWarnings("unchecked")
   346             for (int j = 0, csize = content.size(); j < csize; j++) {
   352             List<XMLStructure> content = obj.getContent();
   347                 XMLStructure xs = (XMLStructure) content.get(j);
   353             for (XMLStructure xs : content) {
   348                 if (xs instanceof Manifest) {
   354                 if (xs instanceof Manifest) {
   349                     Manifest man = (Manifest) xs;
   355                     Manifest man = (Manifest)xs;
   350                     signatureIdMap.put(man.getId(), man);
   356                     signatureIdMap.put(man.getId(), man);
   351                     List manRefs = man.getReferences();
   357                     @SuppressWarnings("unchecked")
   352                     for (int k = 0, msize = manRefs.size(); k < msize; k++) {
   358                     List<Reference> manRefs = man.getReferences();
   353                         Reference ref = (Reference) manRefs.get(k);
   359                     for (Reference ref : manRefs) {
   354                         allReferences.add(ref);
   360                         allReferences.add(ref);
   355                         signatureIdMap.put(ref.getId(), ref);
   361                         signatureIdMap.put(ref.getId(), ref);
   356                     }
   362                     }
   357                 }
   363                 }
   358             }
   364             }
   359         }
   365         }
   360         // always add SignedInfo references after Manifest references so
   366         // always add SignedInfo references after Manifest references so
   361         // that Manifest reference are digested first
   367         // that Manifest reference are digested first
   362         allReferences.addAll(si.getReferences());
   368         allReferences.addAll(refs);
   363 
   369 
   364         // generate/digest each reference
   370         // generate/digest each reference
   365         for (int i = 0, size = allReferences.size(); i < size; i++) {
   371         for (Reference ref : allReferences) {
   366             DOMReference ref = (DOMReference) allReferences.get(i);
   372             digestReference((DOMReference)ref, signContext);
   367             digestReference(ref, signContext);
       
   368         }
   373         }
   369 
   374 
   370         // do final sweep to digest any references that were skipped or missed
   375         // do final sweep to digest any references that were skipped or missed
   371         for (int i = 0, size = allReferences.size(); i < size; i++) {
   376         for (Reference ref : allReferences) {
   372             DOMReference ref = (DOMReference) allReferences.get(i);
   377             if (((DOMReference)ref).isDigested()) {
   373             if (ref.isDigested()) {
       
   374                 continue;
   378                 continue;
   375             }
   379             }
   376             ref.digest(signContext);
   380             ((DOMReference)ref).digest(signContext);
   377         }
   381         }
   378 
   382 
   379         Key signingKey = null;
   383         Key signingKey = null;
   380         KeySelectorResult ksr = null;
   384         KeySelectorResult ksr = null;
   381         try {
   385         try {
   382             ksr = signContext.getKeySelector().select
   386             ksr = signContext.getKeySelector().select(ki,
   383                 (ki, KeySelector.Purpose.SIGN,
   387                                                       KeySelector.Purpose.SIGN,
   384                 si.getSignatureMethod(), signContext);
   388                                                       si.getSignatureMethod(),
       
   389                                                       signContext);
   385             signingKey = ksr.getKey();
   390             signingKey = ksr.getKey();
   386             if (signingKey == null) {
   391             if (signingKey == null) {
   387                 throw new XMLSignatureException("the keySelector did not " +
   392                 throw new XMLSignatureException("the keySelector did not " +
   388                 "find a signing key");
   393                                                 "find a signing key");
   389             }
   394             }
   390         } catch (KeySelectorException kse) {
   395         } catch (KeySelectorException kse) {
   391             throw new XMLSignatureException("cannot find signing key", kse);
   396             throw new XMLSignatureException("cannot find signing key", kse);
   392         }
   397         }
   393 
   398 
   394         // calculate signature value
   399         // calculate signature value
   395         byte[] val = null;
       
   396         try {
   400         try {
   397             val = ((DOMSignatureMethod) si.getSignatureMethod()).sign
   401             byte[] val = ((AbstractDOMSignatureMethod)
   398                 (signingKey, (DOMSignedInfo) si, signContext);
   402                 si.getSignatureMethod()).sign(signingKey, si, signContext);
       
   403             ((DOMSignatureValue)sv).setValue(val);
   399         } catch (InvalidKeyException ike) {
   404         } catch (InvalidKeyException ike) {
   400             throw new XMLSignatureException(ike);
   405             throw new XMLSignatureException(ike);
   401         }
   406         }
   402 
   407 
   403         if (log.isLoggable(Level.FINE)) {
       
   404             log.log(Level.FINE, "SignatureValue = " + val);
       
   405         }
       
   406         ((DOMSignatureValue) sv).setValue(val);
       
   407 
       
   408         this.localSigElem = sigElem;
   408         this.localSigElem = sigElem;
   409         this.ksr = ksr;
   409         this.ksr = ksr;
   410     }
   410     }
   411 
   411 
       
   412     @Override
   412     public boolean equals(Object o) {
   413     public boolean equals(Object o) {
   413         if (this == o) {
   414         if (this == o) {
   414             return true;
   415             return true;
   415         }
   416         }
   416 
   417 
   417         if (!(o instanceof XMLSignature)) {
   418         if (!(o instanceof XMLSignature)) {
   418             return false;
   419             return false;
   419         }
   420         }
   420         XMLSignature osig = (XMLSignature) o;
   421         XMLSignature osig = (XMLSignature)o;
   421 
   422 
   422         boolean idEqual =
   423         boolean idEqual =
   423             (id == null ? osig.getId() == null : id.equals(osig.getId()));
   424             (id == null ? osig.getId() == null : id.equals(osig.getId()));
   424         boolean keyInfoEqual =
   425         boolean keyInfoEqual =
   425             (ki == null ? osig.getKeyInfo() == null :
   426             (ki == null ? osig.getKeyInfo() == null
   426              ki.equals(osig.getKeyInfo()));
   427                         : ki.equals(osig.getKeyInfo()));
   427 
   428 
   428         return (idEqual && keyInfoEqual &&
   429         return (idEqual && keyInfoEqual &&
   429             sv.equals(osig.getSignatureValue()) &&
   430                 sv.equals(osig.getSignatureValue()) &&
   430             si.equals(osig.getSignedInfo()) &&
   431                 si.equals(osig.getSignedInfo()) &&
   431             objects.equals(osig.getObjects()));
   432                 objects.equals(osig.getObjects()));
       
   433     }
       
   434 
       
   435     @Override
       
   436     public int hashCode() {
       
   437         int result = 17;
       
   438         if (id != null) {
       
   439             result = 31 * result + id.hashCode();
       
   440         }
       
   441         if (ki != null) {
       
   442             result = 31 * result + ki.hashCode();
       
   443         }
       
   444         result = 31 * result + sv.hashCode();
       
   445         result = 31 * result + si.hashCode();
       
   446         result = 31 * result + objects.hashCode();
       
   447 
       
   448         return result;
   432     }
   449     }
   433 
   450 
   434     private void digestReference(DOMReference ref, XMLSignContext signContext)
   451     private void digestReference(DOMReference ref, XMLSignContext signContext)
   435         throws XMLSignatureException {
   452         throws XMLSignatureException
       
   453     {
   436         if (ref.isDigested()) {
   454         if (ref.isDigested()) {
   437             return;
   455             return;
   438         }
   456         }
   439         // check dependencies
   457         // check dependencies
   440         String uri = ref.getURI();
   458         String uri = ref.getURI();
   441         if (Utils.sameDocumentURI(uri)) {
   459         if (Utils.sameDocumentURI(uri)) {
   442             String id = Utils.parseIdFromSameDocumentURI(uri);
   460             String id = Utils.parseIdFromSameDocumentURI(uri);
   443             if (id != null && signatureIdMap.containsKey(id)) {
   461             if (id != null && signatureIdMap.containsKey(id)) {
   444                 Object obj = signatureIdMap.get(id);
   462                 XMLStructure xs = signatureIdMap.get(id);
   445                 if (obj instanceof DOMReference) {
   463                 if (xs instanceof DOMReference) {
   446                     digestReference((DOMReference) obj, signContext);
   464                     digestReference((DOMReference)xs, signContext);
   447                 } else if (obj instanceof Manifest) {
   465                 } else if (xs instanceof Manifest) {
   448                     Manifest man = (Manifest) obj;
   466                     Manifest man = (Manifest)xs;
   449                     List manRefs = man.getReferences();
   467                     List manRefs = man.getReferences();
   450                     for (int i = 0, size = manRefs.size(); i < size; i++) {
   468                     for (int i = 0, size = manRefs.size(); i < size; i++) {
   451                         digestReference
   469                         digestReference((DOMReference)manRefs.get(i),
   452                             ((DOMReference) manRefs.get(i), signContext);
   470                                         signContext);
   453                     }
   471                     }
   454                 }
   472                 }
   455             }
   473             }
   456             // if uri="" and there are XPath Transforms, there may be
   474             // if uri="" and there are XPath Transforms, there may be
   457             // reference dependencies in the XPath Transform - so be on
   475             // reference dependencies in the XPath Transform - so be on
   458             // the safe side, and skip and do at end in the final sweep
   476             // the safe side, and skip and do at end in the final sweep
   459             if (uri.length() == 0) {
   477             if (uri.length() == 0) {
   460                 List transforms = ref.getTransforms();
   478                 @SuppressWarnings("unchecked")
   461                 for (int i = 0, size = transforms.size(); i < size; i++) {
   479                 List<Transform> transforms = ref.getTransforms();
   462                     Transform transform = (Transform) transforms.get(i);
   480                 for (Transform transform : transforms) {
   463                     String transformAlg = transform.getAlgorithm();
   481                     String transformAlg = transform.getAlgorithm();
   464                     if (transformAlg.equals(Transform.XPATH) ||
   482                     if (transformAlg.equals(Transform.XPATH) ||
   465                         transformAlg.equals(Transform.XPATH2)) {
   483                         transformAlg.equals(Transform.XPATH2)) {
   466                         return;
   484                         return;
   467                     }
   485                     }
   470         }
   488         }
   471         ref.digest(signContext);
   489         ref.digest(signContext);
   472     }
   490     }
   473 
   491 
   474     public class DOMSignatureValue extends DOMStructure
   492     public class DOMSignatureValue extends DOMStructure
   475         implements SignatureValue {
   493         implements SignatureValue
   476 
   494     {
   477         private String id;
   495         private String id;
   478         private byte[] value;
   496         private byte[] value;
   479         private String valueBase64;
   497         private String valueBase64;
   480         private Element sigValueElem;
   498         private Element sigValueElem;
   481         private boolean validated = false;
   499         private boolean validated = false;
   483 
   501 
   484         DOMSignatureValue(String id) {
   502         DOMSignatureValue(String id) {
   485             this.id = id;
   503             this.id = id;
   486         }
   504         }
   487 
   505 
   488         DOMSignatureValue(Element sigValueElem) throws MarshalException {
   506         DOMSignatureValue(Element sigValueElem, XMLCryptoContext context)
       
   507             throws MarshalException
       
   508         {
   489             try {
   509             try {
   490                 // base64 decode signatureValue
   510                 // base64 decode signatureValue
   491                 value = Base64.decode(sigValueElem);
   511                 value = Base64.decode(sigValueElem);
   492             } catch (Base64DecodingException bde) {
   512             } catch (Base64DecodingException bde) {
   493                 throw new MarshalException(bde);
   513                 throw new MarshalException(bde);
   506         public String getId() {
   526         public String getId() {
   507             return id;
   527             return id;
   508         }
   528         }
   509 
   529 
   510         public byte[] getValue() {
   530         public byte[] getValue() {
   511             return (value == null) ? null : (byte[]) value.clone();
   531             return (value == null) ? null : (byte[])value.clone();
   512         }
   532         }
   513 
   533 
   514         public boolean validate(XMLValidateContext validateContext)
   534         public boolean validate(XMLValidateContext validateContext)
   515             throws XMLSignatureException {
   535             throws XMLSignatureException
   516 
   536         {
   517             if (validateContext == null) {
   537             if (validateContext == null) {
   518                 throw new NullPointerException("context cannot be null");
   538                 throw new NullPointerException("context cannot be null");
   519             }
   539             }
   520 
   540 
   521             if (validated) {
   541             if (validated) {
   529             try {
   549             try {
   530                 ksResult = validateContext.getKeySelector().select
   550                 ksResult = validateContext.getKeySelector().select
   531                     (ki, KeySelector.Purpose.VERIFY, sm, validateContext);
   551                     (ki, KeySelector.Purpose.VERIFY, sm, validateContext);
   532                 validationKey = ksResult.getKey();
   552                 validationKey = ksResult.getKey();
   533                 if (validationKey == null) {
   553                 if (validationKey == null) {
   534                     throw new XMLSignatureException("the keyselector did " +
   554                     throw new XMLSignatureException("the keyselector did not " +
   535                         "not find a validation key");
   555                                                     "find a validation key");
   536                 }
   556                 }
   537             } catch (KeySelectorException kse) {
   557             } catch (KeySelectorException kse) {
   538                 throw new XMLSignatureException("cannot find validation " +
   558                 throw new XMLSignatureException("cannot find validation " +
   539                     "key", kse);
   559                                                 "key", kse);
   540             }
   560             }
   541 
   561 
   542             // canonicalize SignedInfo and verify signature
   562             // canonicalize SignedInfo and verify signature
   543             try {
   563             try {
   544                 validationStatus = ((DOMSignatureMethod) sm).verify
   564                 validationStatus = ((AbstractDOMSignatureMethod)sm).verify
   545                     (validationKey, (DOMSignedInfo) si, value, validateContext);
   565                     (validationKey, si, value, validateContext);
   546             } catch (Exception e) {
   566             } catch (Exception e) {
   547                 throw new XMLSignatureException(e);
   567                 throw new XMLSignatureException(e);
   548             }
   568             }
   549 
   569 
   550             validated = true;
   570             validated = true;
   551             ksr = ksResult;
   571             ksr = ksResult;
   552             return validationStatus;
   572             return validationStatus;
   553         }
   573         }
   554 
   574 
       
   575         @Override
   555         public boolean equals(Object o) {
   576         public boolean equals(Object o) {
   556             if (this == o) {
   577             if (this == o) {
   557                 return true;
   578                 return true;
   558             }
   579             }
   559 
   580 
   560             if (!(o instanceof SignatureValue)) {
   581             if (!(o instanceof SignatureValue)) {
   561                 return false;
   582                 return false;
   562             }
   583             }
   563             SignatureValue osv = (SignatureValue) o;
   584             SignatureValue osv = (SignatureValue)o;
   564 
   585 
   565             boolean idEqual =
   586             boolean idEqual =
   566                 (id == null ? osv.getId() == null : id.equals(osv.getId()));
   587                 (id == null ? osv.getId() == null : id.equals(osv.getId()));
   567 
   588 
   568             //XXX compare signature values?
   589             //XXX compare signature values?
   569             return idEqual;
   590             return idEqual;
   570         }
   591         }
   571 
   592 
       
   593         @Override
       
   594         public int hashCode() {
       
   595             int result = 17;
       
   596             if (id != null) {
       
   597                 result = 31 * result + id.hashCode();
       
   598             }
       
   599 
       
   600             return result;
       
   601         }
       
   602 
   572         public void marshal(Node parent, String dsPrefix,
   603         public void marshal(Node parent, String dsPrefix,
   573             DOMCryptoContext context) throws MarshalException {
   604                             DOMCryptoContext context)
   574 
   605             throws MarshalException
       
   606         {
   575             // create SignatureValue element
   607             // create SignatureValue element
   576             sigValueElem = DOMUtils.createElement
   608             sigValueElem = DOMUtils.createElement(ownerDoc, "SignatureValue",
   577                 (ownerDoc, "SignatureValue", XMLSignature.XMLNS, dsPrefix);
   609                                                   XMLSignature.XMLNS, dsPrefix);
   578             if (valueBase64 != null) {
   610             if (valueBase64 != null) {
   579                 sigValueElem.appendChild(ownerDoc.createTextNode(valueBase64));
   611                 sigValueElem.appendChild(ownerDoc.createTextNode(valueBase64));
   580             }
   612             }
   581 
   613 
   582             // append Id attribute, if specified
   614             // append Id attribute, if specified