src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java

Print this page


   1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2005 The Apache Software Foundation.
   7  *
   8  *  Licensed under the Apache License, Version 2.0 (the "License");
   9  *  you may not use this file except in compliance with the License.
  10  *  You may obtain a copy of the License at


  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  *  Unless required by applicable law or agreed to in writing, software
  15  *  distributed under the License is distributed on an "AS IS" BASIS,
  16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  *  See the License for the specific language governing permissions and
  18  *  limitations under the License.
  19  *
  20  */
  21 /*
  22  * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * $Id: DOMSignedInfo.java,v 1.2 2008/07/24 15:20:32 mullan Exp $
  26  */
  27 package org.jcp.xml.dsig.internal.dom;
  28 
  29 import javax.xml.crypto.*;
  30 import javax.xml.crypto.dom.DOMCryptoContext;
  31 import javax.xml.crypto.dsig.*;
  32 
  33 import java.io.ByteArrayInputStream;
  34 import java.io.ByteArrayOutputStream;
  35 import java.io.InputStream;
  36 import java.io.IOException;
  37 import java.io.InputStreamReader;
  38 import java.io.OutputStream;

  39 import java.security.Provider;
  40 import java.util.*;
  41 import java.util.logging.Level;
  42 import java.util.logging.Logger;
  43 import org.w3c.dom.Document;
  44 import org.w3c.dom.Element;
  45 import org.w3c.dom.Node;
  46 
  47 import com.sun.org.apache.xml.internal.security.utils.Base64;
  48 import com.sun.org.apache.xml.internal.security.utils.Constants;
  49 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
  50 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
  51 
  52 /**
  53  * DOM-based implementation of SignedInfo.
  54  *
  55  * @author Sean Mullan
  56  */
  57 public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
  58 
  59     /**
  60      * The maximum number of references per Manifest, if secure validation is
  61      * enabled.
  62      */
  63     public static final int MAXIMUM_REFERENCE_COUNT = 30;
  64 
  65     private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom");

  66 
  67     /** Signature - NOT Recommended RSAwithMD5 */
  68     private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
  69         Constants.MoreAlgorithmsSpecNS + "rsa-md5";
  70 
  71     /** HMAC - NOT Recommended HMAC-MD5 */
  72     private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
  73         Constants.MoreAlgorithmsSpecNS + "hmac-md5";
  74 
  75     private List references;
  76     private CanonicalizationMethod canonicalizationMethod;
  77     private SignatureMethod signatureMethod;
  78     private String id;
  79     private Document ownerDoc;
  80     private Element localSiElem;
  81     private InputStream canonData;
  82 
  83     /**
  84      * Creates a <code>DOMSignedInfo</code> from the specified parameters. Use
  85      * this constructor when the <code>Id</code> is not specified.
  86      *
  87      * @param cm the canonicalization method
  88      * @param sm the signature method
  89      * @param references the list of references. The list is copied.
  90      * @throws NullPointerException if
  91      *    <code>cm</code>, <code>sm</code>, or <code>references</code> is
  92      *    <code>null</code>
  93      * @throws IllegalArgumentException if <code>references</code> is empty
  94      * @throws ClassCastException if any of the references are not of
  95      *    type <code>Reference</code>
  96      */
  97     public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
  98         List references) {
  99         if (cm == null || sm == null || references == null) {
 100             throw new NullPointerException();
 101         }
 102         this.canonicalizationMethod = cm;
 103         this.signatureMethod = sm;
 104         this.references = Collections.unmodifiableList
 105             (new ArrayList(references));
 106         if (this.references.isEmpty()) {
 107             throw new IllegalArgumentException("list of references must " +
 108                 "contain at least one entry");
 109         }
 110         for (int i = 0, size = this.references.size(); i < size; i++) {
 111             Object obj = this.references.get(i);
 112             if (!(obj instanceof Reference)) {
 113                 throw new ClassCastException("list of references contains " +
 114                     "an illegal type");
 115             }
 116         }
 117     }
 118 
 119     /**
 120      * Creates a <code>DOMSignedInfo</code> from the specified parameters.
 121      *
 122      * @param cm the canonicalization method
 123      * @param sm the signature method
 124      * @param references the list of references. The list is copied.
 125      * @param id an optional identifer that will allow this
 126      *    <code>SignedInfo</code> to be referenced by other signatures and
 127      *    objects
 128      * @throws NullPointerException if <code>cm</code>, <code>sm</code>,
 129      *    or <code>references</code> is <code>null</code>
 130      * @throws IllegalArgumentException if <code>references</code> is empty
 131      * @throws ClassCastException if any of the references are not of
 132      *    type <code>Reference</code>
 133      */
 134     public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
 135         List references, String id) {
 136         this(cm, sm, references);
 137         this.id = id;
 138     }
 139 
 140     /**
 141      * Creates a <code>DOMSignedInfo</code> from an element.
 142      *
 143      * @param siElem a SignedInfo element
 144      */
 145     public DOMSignedInfo(Element siElem, XMLCryptoContext context,
 146         Provider provider) throws MarshalException {
 147         localSiElem = siElem;
 148         ownerDoc = siElem.getOwnerDocument();
 149 
 150         // get Id attribute, if specified
 151         id = DOMUtils.getAttributeValue(siElem, "Id");
 152 
 153         // unmarshal CanonicalizationMethod
 154         Element cmElem = DOMUtils.getFirstChildElement(siElem);
 155         canonicalizationMethod = new DOMCanonicalizationMethod
 156             (cmElem, context, provider);
 157 
 158         // unmarshal SignatureMethod
 159         Element smElem = DOMUtils.getNextSiblingElement(cmElem);
 160         signatureMethod = DOMSignatureMethod.unmarshal(smElem);
 161 
 162         boolean secVal = Utils.secureValidation(context);
 163         String sigMethAlg = signatureMethod.getAlgorithm();
 164         if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(sigMethAlg)
 165             || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(sigMethAlg))))
 166         {
 167             throw new MarshalException("It is forbidden to use algorithm " +
 168                                        signatureMethod +
 169                                        " when secure validation is enabled");
 170         }
 171 
 172         // unmarshal References
 173         ArrayList refList = new ArrayList(5);
 174         Element refElem = DOMUtils.getNextSiblingElement(smElem);

 175         int refCount = 0;
 176         while (refElem != null) {
 177             refList.add(new DOMReference(refElem, context, provider));
 178             refElem = DOMUtils.getNextSiblingElement(refElem);
 179 
 180             refCount++;
 181             if (secVal && (refCount > MAXIMUM_REFERENCE_COUNT)) {
 182                 String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT +
 183                                " references per SignedInfo are allowed with" +
 184                                " secure validation";
 185                 throw new MarshalException(error);
 186             }
 187         }
 188         references = Collections.unmodifiableList(refList);
 189     }
 190 
 191     public CanonicalizationMethod getCanonicalizationMethod() {
 192         return canonicalizationMethod;
 193     }
 194 
 195     public SignatureMethod getSignatureMethod() {
 196         return signatureMethod;
 197     }
 198 
 199     public String getId() {
 200         return id;
 201     }
 202 
 203     public List getReferences() {
 204         return references;
 205     }
 206 
 207     public InputStream getCanonicalizedData() {
 208         return canonData;
 209     }
 210 
 211     public void canonicalize(XMLCryptoContext context,ByteArrayOutputStream bos)
 212         throws XMLSignatureException {
 213 
 214         if (context == null) {
 215             throw new NullPointerException("context cannot be null");
 216         }
 217 
 218         OutputStream os = new UnsyncBufferedOutputStream(bos);
 219         try {
 220             os.close();
 221         } catch (IOException e) {



 222             // Impossible
 223         }
 224 
 225         DOMSubTreeData subTree = new DOMSubTreeData(localSiElem, true);
 226 
 227         try {
 228             Data data = ((DOMCanonicalizationMethod)
 229                 canonicalizationMethod).canonicalize(subTree, context, os);
 230         } catch (TransformException te) {
 231             throw new XMLSignatureException(te);
 232         }
 233 
 234         byte[] signedInfoBytes = bos.toByteArray();
 235 
 236         // this whole block should only be done if logging is enabled
 237         if (log.isLoggable(Level.FINE)) {
 238             InputStreamReader isr = new InputStreamReader
 239                 (new ByteArrayInputStream(signedInfoBytes));
 240             char[] siBytes = new char[signedInfoBytes.length];
 241             try {
 242                 isr.read(siBytes);
 243                 log.log(Level.FINE, "Canonicalized SignedInfo:\n"
 244                     + new String(siBytes));
 245             } catch (IOException ioex) {
 246                 log.log(Level.FINE, "IOException reading SignedInfo bytes");
 247             }
 248             log.log(Level.FINE, "Data to be signed/verified:"
 249                 + Base64.encode(signedInfoBytes));
 250         }
 251 
 252         this.canonData = new ByteArrayInputStream(signedInfoBytes);
 253     }
 254 
 255     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
 256         throws MarshalException {

 257         ownerDoc = DOMUtils.getOwnerDocument(parent);
 258 
 259         Element siElem = DOMUtils.createElement
 260             (ownerDoc, "SignedInfo", XMLSignature.XMLNS, dsPrefix);
 261 
 262         // create and append CanonicalizationMethod element
 263         DOMCanonicalizationMethod dcm =
 264             (DOMCanonicalizationMethod) canonicalizationMethod;
 265         dcm.marshal(siElem, dsPrefix, context);
 266 
 267         // create and append SignatureMethod element
 268         ((DOMSignatureMethod) signatureMethod).marshal
 269             (siElem, dsPrefix, context);
 270 
 271         // create and append Reference elements
 272         for (int i = 0, size = references.size(); i < size; i++) {
 273             DOMReference reference = (DOMReference) references.get(i);
 274             reference.marshal(siElem, dsPrefix, context);
 275         }
 276 
 277         // append Id attribute
 278         DOMUtils.setAttributeID(siElem, "Id", id);
 279 
 280         parent.appendChild(siElem);
 281         localSiElem = siElem;
 282     }
 283 

 284     public boolean equals(Object o) {
 285         if (this == o) {
 286             return true;
 287         }
 288 
 289         if (!(o instanceof SignedInfo)) {
 290             return false;
 291         }
 292         SignedInfo osi = (SignedInfo) o;
 293 
 294         boolean idEqual = (id == null ? osi.getId() == null :
 295             id.equals(osi.getId()));
 296 
 297         return (canonicalizationMethod.equals(osi.getCanonicalizationMethod())
 298             && signatureMethod.equals(osi.getSignatureMethod()) &&
 299             references.equals(osi.getReferences()) && idEqual);













 300     }
 301 }
   1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /**
   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
  13  *
  14  * http://www.apache.org/licenses/LICENSE-2.0
  15  *
  16  * Unless required by applicable law or agreed to in writing,
  17  * software distributed under the License is distributed on an
  18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  19  * KIND, either express or implied. See the License for the
  20  * specific language governing permissions and limitations
  21  * under the License.
  22  */
  23 /*
  24  * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
  25  */
  26 /*
  27  * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
  28  */
  29 package org.jcp.xml.dsig.internal.dom;
  30 
  31 import javax.xml.crypto.*;
  32 import javax.xml.crypto.dom.DOMCryptoContext;
  33 import javax.xml.crypto.dsig.*;
  34 
  35 import java.io.ByteArrayInputStream;
  36 import java.io.ByteArrayOutputStream;
  37 import java.io.InputStream;


  38 import java.io.OutputStream;
  39 import java.io.IOException;
  40 import java.security.Provider;
  41 import java.util.*;
  42 

  43 import org.w3c.dom.Document;
  44 import org.w3c.dom.Element;
  45 import org.w3c.dom.Node;
  46 
  47 import com.sun.org.apache.xml.internal.security.utils.Base64;
  48 import com.sun.org.apache.xml.internal.security.utils.Constants;
  49 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;

  50 
  51 /**
  52  * DOM-based implementation of SignedInfo.
  53  *
  54  * @author Sean Mullan
  55  */
  56 public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
  57     
  58     /**
  59      * The maximum number of references per Manifest, if secure validation is enabled.

  60      */
  61     public static final int MAXIMUM_REFERENCE_COUNT = 30;
  62 
  63     private static java.util.logging.Logger log =
  64         java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
  65     
  66     /** Signature - NOT Recommended RSAwithMD5 */
  67     private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 = 
  68         Constants.MoreAlgorithmsSpecNS + "rsa-md5";
  69     
  70     /** HMAC - NOT Recommended HMAC-MD5 */
  71     private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 = 
  72         Constants.MoreAlgorithmsSpecNS + "hmac-md5";
  73     
  74     private List<Reference> references;
  75     private CanonicalizationMethod canonicalizationMethod;
  76     private SignatureMethod signatureMethod;
  77     private String id;
  78     private Document ownerDoc;
  79     private Element localSiElem;
  80     private InputStream canonData;
  81 
  82     /**
  83      * Creates a <code>DOMSignedInfo</code> from the specified parameters. Use
  84      * this constructor when the <code>Id</code> is not specified.
  85      *
  86      * @param cm the canonicalization method
  87      * @param sm the signature method
  88      * @param references the list of references. The list is copied.
  89      * @throws NullPointerException if
  90      *    <code>cm</code>, <code>sm</code>, or <code>references</code> is 
  91      *    <code>null</code>
  92      * @throws IllegalArgumentException if <code>references</code> is empty
  93      * @throws ClassCastException if any of the references are not of
  94      *    type <code>Reference</code>
  95      */
  96     public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
  97                          List<? extends Reference> references) {
  98         if (cm == null || sm == null || references == null) {
  99             throw new NullPointerException();
 100         }
 101         this.canonicalizationMethod = cm;
 102         this.signatureMethod = sm;
 103         this.references = Collections.unmodifiableList(
 104             new ArrayList<Reference>(references));
 105         if (this.references.isEmpty()) {
 106             throw new IllegalArgumentException("list of references must " +
 107                 "contain at least one entry");
 108         }
 109         for (int i = 0, size = this.references.size(); i < size; i++) {
 110             Object obj = this.references.get(i);
 111             if (!(obj instanceof Reference)) {
 112                 throw new ClassCastException("list of references contains " +
 113                     "an illegal type");
 114             }
 115         }
 116     }
 117 
 118     /**
 119      * Creates a <code>DOMSignedInfo</code> from the specified parameters.
 120      *
 121      * @param cm the canonicalization method
 122      * @param sm the signature method
 123      * @param references the list of references. The list is copied.
 124      * @param id an optional identifer that will allow this
 125      *    <code>SignedInfo</code> to be referenced by other signatures and
 126      *    objects
 127      * @throws NullPointerException if <code>cm</code>, <code>sm</code>,
 128      *    or <code>references</code> is <code>null</code>
 129      * @throws IllegalArgumentException if <code>references</code> is empty
 130      * @throws ClassCastException if any of the references are not of
 131      *    type <code>Reference</code>
 132      */
 133     public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm, 
 134                          List<? extends Reference> references, String id) {
 135         this(cm, sm, references);
 136         this.id = id;
 137     }
 138 
 139     /**
 140      * Creates a <code>DOMSignedInfo</code> from an element.
 141      *
 142      * @param siElem a SignedInfo element
 143      */
 144     public DOMSignedInfo(Element siElem, XMLCryptoContext context, Provider provider)
 145         throws MarshalException {
 146         localSiElem = siElem;
 147         ownerDoc = siElem.getOwnerDocument();
 148 
 149         // get Id attribute, if specified
 150         id = DOMUtils.getAttributeValue(siElem, "Id");
 151 
 152         // unmarshal CanonicalizationMethod
 153         Element cmElem = DOMUtils.getFirstChildElement(siElem);
 154         canonicalizationMethod = new DOMCanonicalizationMethod(cmElem, context, provider);

 155 
 156         // unmarshal SignatureMethod
 157         Element smElem = DOMUtils.getNextSiblingElement(cmElem);
 158         signatureMethod = DOMSignatureMethod.unmarshal(smElem);
 159         
 160         boolean secVal = Utils.secureValidation(context);
 161 
 162         String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
 163         if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
 164                 || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
 165             throw new MarshalException(
 166                 "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
 167             );
 168         }
 169         
 170         // unmarshal References
 171         ArrayList<Reference> refList = new ArrayList<Reference>(5);
 172         Element refElem = DOMUtils.getNextSiblingElement(smElem);
 173         
 174         int refCount = 0;
 175         while (refElem != null) {
 176             refList.add(new DOMReference(refElem, context, provider));
 177             refElem = DOMUtils.getNextSiblingElement(refElem);
 178             
 179             refCount++;
 180             if (secVal && (refCount > MAXIMUM_REFERENCE_COUNT)) {
 181                 String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " " 
 182                     + "references per Manifest are allowed with secure validation";

 183                 throw new MarshalException(error);
 184             }
 185         }
 186         references = Collections.unmodifiableList(refList);
 187     }
 188 
 189     public CanonicalizationMethod getCanonicalizationMethod() {
 190         return canonicalizationMethod;
 191     }
 192 
 193     public SignatureMethod getSignatureMethod() {
 194         return signatureMethod;
 195     }
 196 
 197     public String getId() {
 198         return id;
 199     }
 200 
 201     public List getReferences() {
 202         return references;
 203     }
 204 
 205     public InputStream getCanonicalizedData() {
 206         return canonData;
 207     }
 208 
 209     public void canonicalize(XMLCryptoContext context, ByteArrayOutputStream bos)
 210         throws XMLSignatureException {

 211         if (context == null) {
 212             throw new NullPointerException("context cannot be null");
 213         }
 214 
 215         OutputStream os = new UnsyncBufferedOutputStream(bos);
 216         try {
 217             os.close();
 218         } catch (IOException e) {
 219             if (log.isLoggable(java.util.logging.Level.FINE)) {
 220                 log.log(java.util.logging.Level.FINE, e.getMessage(), e);
 221             }
 222             // Impossible
 223         }
 224 
 225         DOMSubTreeData subTree = new DOMSubTreeData(localSiElem, true);
 226 
 227         try {
 228             ((DOMCanonicalizationMethod) 
 229                 canonicalizationMethod).canonicalize(subTree, context, bos);
 230         } catch (TransformException te) {
 231             throw new XMLSignatureException(te);
 232         }
 233 
 234         byte[] signedInfoBytes = bos.toByteArray();
 235 
 236         // this whole block should only be done if logging is enabled
 237         if (log.isLoggable(java.util.logging.Level.FINE)) {
 238             log.log(java.util.logging.Level.FINE, "Canonicalized SignedInfo:"); 
 239             StringBuilder sb = new StringBuilder(signedInfoBytes.length);
 240             for (int i = 0; i < signedInfoBytes.length; i++) {
 241                 sb.append((char)signedInfoBytes[i]);





 242             }
 243             log.log(java.util.logging.Level.FINE, sb.toString());
 244             log.log(java.util.logging.Level.FINE, "Data to be signed/verified:" + Base64.encode(signedInfoBytes));
 245         }
 246 
 247         this.canonData = new ByteArrayInputStream(signedInfoBytes);
 248     }
 249 
 250     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
 251         throws MarshalException
 252     {
 253         ownerDoc = DOMUtils.getOwnerDocument(parent);
 254         Element siElem = DOMUtils.createElement(ownerDoc, "SignedInfo",
 255                                                 XMLSignature.XMLNS, dsPrefix);

 256 
 257         // create and append CanonicalizationMethod element
 258         DOMCanonicalizationMethod dcm =
 259             (DOMCanonicalizationMethod)canonicalizationMethod;
 260         dcm.marshal(siElem, dsPrefix, context); 
 261 
 262         // create and append SignatureMethod element
 263         ((DOMStructure)signatureMethod).marshal(siElem, dsPrefix, context);

 264 
 265         // create and append Reference elements
 266         for (Reference reference : references) {
 267             ((DOMReference)reference).marshal(siElem, dsPrefix, context);

 268         }
 269 
 270         // append Id attribute
 271         DOMUtils.setAttributeID(siElem, "Id", id);
 272             
 273         parent.appendChild(siElem);
 274         localSiElem = siElem;
 275     }
 276 
 277     @Override
 278     public boolean equals(Object o) {
 279         if (this == o) {
 280             return true;
 281         }
 282 
 283         if (!(o instanceof SignedInfo)) {
 284             return false;
 285         }
 286         SignedInfo osi = (SignedInfo)o;
 287 
 288         boolean idEqual = (id == null ? osi.getId() == null
 289                                       : id.equals(osi.getId()));
 290 
 291         return (canonicalizationMethod.equals(osi.getCanonicalizationMethod()) 
 292                 && signatureMethod.equals(osi.getSignatureMethod()) && 
 293                 references.equals(osi.getReferences()) && idEqual);
 294     }
 295     
 296     @Override
 297     public int hashCode() {
 298         int result = 17;
 299         if (id != null) {
 300             result = 31 * result + id.hashCode();
 301         }
 302         result = 31 * result + canonicalizationMethod.hashCode();
 303         result = 31 * result + signatureMethod.hashCode();
 304         result = 31 * result + references.hashCode();
 305         
 306         return result;
 307     }
 308 }