src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
Print this page
*** 1,80 ****
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
! /*
! * Copyright 2005 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.
! *
*/
/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
*/
/*
! * $Id: DOMSignedInfo.java,v 1.2 2008/07/24 15:20:32 mullan Exp $
*/
package org.jcp.xml.dsig.internal.dom;
import javax.xml.crypto.*;
import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.Provider;
import java.util.*;
! import java.util.logging.Level;
! import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
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.UnsyncBufferedOutputStream;
- import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
/**
* DOM-based implementation of SignedInfo.
*
* @author Sean Mullan
*/
public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
/**
! * The maximum number of references per Manifest, if secure validation is
! * enabled.
*/
public static final int MAXIMUM_REFERENCE_COUNT = 30;
! private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom");
/** Signature - NOT Recommended RSAwithMD5 */
private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
Constants.MoreAlgorithmsSpecNS + "rsa-md5";
/** HMAC - NOT Recommended HMAC-MD5 */
private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
Constants.MoreAlgorithmsSpecNS + "hmac-md5";
! private List references;
private CanonicalizationMethod canonicalizationMethod;
private SignatureMethod signatureMethod;
private String id;
private Document ownerDoc;
private Element localSiElem;
--- 1,79 ----
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
! /**
! * Licensed to the Apache Software Foundation (ASF) under one
! * or more contributor license agreements. See the NOTICE file
! * distributed with this work for additional information
! * regarding copyright ownership. The ASF licenses this file
! * to you 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.
*/
/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
*/
/*
! * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
*/
package org.jcp.xml.dsig.internal.dom;
import javax.xml.crypto.*;
import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
+ import java.io.IOException;
import java.security.Provider;
import java.util.*;
!
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
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.UnsyncBufferedOutputStream;
/**
* DOM-based implementation of SignedInfo.
*
* @author Sean Mullan
*/
public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
/**
! * The maximum number of references per Manifest, if secure validation is enabled.
*/
public static final int MAXIMUM_REFERENCE_COUNT = 30;
! private static java.util.logging.Logger log =
! java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
/** Signature - NOT Recommended RSAwithMD5 */
private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
Constants.MoreAlgorithmsSpecNS + "rsa-md5";
/** HMAC - NOT Recommended HMAC-MD5 */
private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
Constants.MoreAlgorithmsSpecNS + "hmac-md5";
! private List<Reference> references;
private CanonicalizationMethod canonicalizationMethod;
private SignatureMethod signatureMethod;
private String id;
private Document ownerDoc;
private Element localSiElem;
*** 93,110 ****
* @throws IllegalArgumentException if <code>references</code> is empty
* @throws ClassCastException if any of the references are not of
* type <code>Reference</code>
*/
public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
! List references) {
if (cm == null || sm == null || references == null) {
throw new NullPointerException();
}
this.canonicalizationMethod = cm;
this.signatureMethod = sm;
! this.references = Collections.unmodifiableList
! (new ArrayList(references));
if (this.references.isEmpty()) {
throw new IllegalArgumentException("list of references must " +
"contain at least one entry");
}
for (int i = 0, size = this.references.size(); i < size; i++) {
--- 92,109 ----
* @throws IllegalArgumentException if <code>references</code> is empty
* @throws ClassCastException if any of the references are not of
* type <code>Reference</code>
*/
public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
! List<? extends Reference> references) {
if (cm == null || sm == null || references == null) {
throw new NullPointerException();
}
this.canonicalizationMethod = cm;
this.signatureMethod = sm;
! this.references = Collections.unmodifiableList(
! new ArrayList<Reference>(references));
if (this.references.isEmpty()) {
throw new IllegalArgumentException("list of references must " +
"contain at least one entry");
}
for (int i = 0, size = this.references.size(); i < size; i++) {
*** 130,189 ****
* @throws IllegalArgumentException if <code>references</code> is empty
* @throws ClassCastException if any of the references are not of
* type <code>Reference</code>
*/
public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
! List references, String id) {
this(cm, sm, references);
this.id = id;
}
/**
* Creates a <code>DOMSignedInfo</code> from an element.
*
* @param siElem a SignedInfo element
*/
! public DOMSignedInfo(Element siElem, XMLCryptoContext context,
! Provider provider) throws MarshalException {
localSiElem = siElem;
ownerDoc = siElem.getOwnerDocument();
// get Id attribute, if specified
id = DOMUtils.getAttributeValue(siElem, "Id");
// unmarshal CanonicalizationMethod
Element cmElem = DOMUtils.getFirstChildElement(siElem);
! canonicalizationMethod = new DOMCanonicalizationMethod
! (cmElem, context, provider);
// unmarshal SignatureMethod
Element smElem = DOMUtils.getNextSiblingElement(cmElem);
signatureMethod = DOMSignatureMethod.unmarshal(smElem);
boolean secVal = Utils.secureValidation(context);
! String sigMethAlg = signatureMethod.getAlgorithm();
! if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(sigMethAlg)
! || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(sigMethAlg))))
! {
! throw new MarshalException("It is forbidden to use algorithm " +
! signatureMethod +
! " when secure validation is enabled");
}
// unmarshal References
! ArrayList refList = new ArrayList(5);
Element refElem = DOMUtils.getNextSiblingElement(smElem);
int refCount = 0;
while (refElem != null) {
refList.add(new DOMReference(refElem, context, provider));
refElem = DOMUtils.getNextSiblingElement(refElem);
refCount++;
if (secVal && (refCount > MAXIMUM_REFERENCE_COUNT)) {
! String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT +
! " references per SignedInfo are allowed with" +
! " secure validation";
throw new MarshalException(error);
}
}
references = Collections.unmodifiableList(refList);
}
--- 129,187 ----
* @throws IllegalArgumentException if <code>references</code> is empty
* @throws ClassCastException if any of the references are not of
* type <code>Reference</code>
*/
public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm,
! List<? extends Reference> references, String id) {
this(cm, sm, references);
this.id = id;
}
/**
* Creates a <code>DOMSignedInfo</code> from an element.
*
* @param siElem a SignedInfo element
*/
! public DOMSignedInfo(Element siElem, XMLCryptoContext context, Provider provider)
! throws MarshalException {
localSiElem = siElem;
ownerDoc = siElem.getOwnerDocument();
// get Id attribute, if specified
id = DOMUtils.getAttributeValue(siElem, "Id");
// unmarshal CanonicalizationMethod
Element cmElem = DOMUtils.getFirstChildElement(siElem);
! canonicalizationMethod = new DOMCanonicalizationMethod(cmElem, context, provider);
// unmarshal SignatureMethod
Element smElem = DOMUtils.getNextSiblingElement(cmElem);
signatureMethod = DOMSignatureMethod.unmarshal(smElem);
boolean secVal = Utils.secureValidation(context);
!
! String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
! if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
! || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
! throw new MarshalException(
! "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
! );
}
// unmarshal References
! ArrayList<Reference> refList = new ArrayList<Reference>(5);
Element refElem = DOMUtils.getNextSiblingElement(smElem);
+
int refCount = 0;
while (refElem != null) {
refList.add(new DOMReference(refElem, context, provider));
refElem = DOMUtils.getNextSiblingElement(refElem);
refCount++;
if (secVal && (refCount > MAXIMUM_REFERENCE_COUNT)) {
! String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " "
! + "references per Manifest are allowed with secure validation";
throw new MarshalException(error);
}
}
references = Collections.unmodifiableList(refList);
}
*** 206,301 ****
public InputStream getCanonicalizedData() {
return canonData;
}
! public void canonicalize(XMLCryptoContext context,ByteArrayOutputStream bos)
throws XMLSignatureException {
-
if (context == null) {
throw new NullPointerException("context cannot be null");
}
OutputStream os = new UnsyncBufferedOutputStream(bos);
try {
os.close();
} catch (IOException e) {
// Impossible
}
DOMSubTreeData subTree = new DOMSubTreeData(localSiElem, true);
try {
! Data data = ((DOMCanonicalizationMethod)
! canonicalizationMethod).canonicalize(subTree, context, os);
} catch (TransformException te) {
throw new XMLSignatureException(te);
}
byte[] signedInfoBytes = bos.toByteArray();
// this whole block should only be done if logging is enabled
! if (log.isLoggable(Level.FINE)) {
! InputStreamReader isr = new InputStreamReader
! (new ByteArrayInputStream(signedInfoBytes));
! char[] siBytes = new char[signedInfoBytes.length];
! try {
! isr.read(siBytes);
! log.log(Level.FINE, "Canonicalized SignedInfo:\n"
! + new String(siBytes));
! } catch (IOException ioex) {
! log.log(Level.FINE, "IOException reading SignedInfo bytes");
}
! log.log(Level.FINE, "Data to be signed/verified:"
! + Base64.encode(signedInfoBytes));
}
this.canonData = new ByteArrayInputStream(signedInfoBytes);
}
public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
! throws MarshalException {
ownerDoc = DOMUtils.getOwnerDocument(parent);
!
! Element siElem = DOMUtils.createElement
! (ownerDoc, "SignedInfo", XMLSignature.XMLNS, dsPrefix);
// create and append CanonicalizationMethod element
DOMCanonicalizationMethod dcm =
! (DOMCanonicalizationMethod) canonicalizationMethod;
dcm.marshal(siElem, dsPrefix, context);
// create and append SignatureMethod element
! ((DOMSignatureMethod) signatureMethod).marshal
! (siElem, dsPrefix, context);
// create and append Reference elements
! for (int i = 0, size = references.size(); i < size; i++) {
! DOMReference reference = (DOMReference) references.get(i);
! reference.marshal(siElem, dsPrefix, context);
}
// append Id attribute
DOMUtils.setAttributeID(siElem, "Id", id);
parent.appendChild(siElem);
localSiElem = siElem;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SignedInfo)) {
return false;
}
! SignedInfo osi = (SignedInfo) o;
! boolean idEqual = (id == null ? osi.getId() == null :
! id.equals(osi.getId()));
return (canonicalizationMethod.equals(osi.getCanonicalizationMethod())
&& signatureMethod.equals(osi.getSignatureMethod()) &&
references.equals(osi.getReferences()) && idEqual);
}
}
--- 204,308 ----
public InputStream getCanonicalizedData() {
return canonData;
}
! public void canonicalize(XMLCryptoContext context, ByteArrayOutputStream bos)
throws XMLSignatureException {
if (context == null) {
throw new NullPointerException("context cannot be null");
}
OutputStream os = new UnsyncBufferedOutputStream(bos);
try {
os.close();
} catch (IOException e) {
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, e.getMessage(), e);
+ }
// Impossible
}
DOMSubTreeData subTree = new DOMSubTreeData(localSiElem, true);
try {
! ((DOMCanonicalizationMethod)
! canonicalizationMethod).canonicalize(subTree, context, bos);
} catch (TransformException te) {
throw new XMLSignatureException(te);
}
byte[] signedInfoBytes = bos.toByteArray();
// this whole block should only be done if logging is enabled
! if (log.isLoggable(java.util.logging.Level.FINE)) {
! log.log(java.util.logging.Level.FINE, "Canonicalized SignedInfo:");
! StringBuilder sb = new StringBuilder(signedInfoBytes.length);
! for (int i = 0; i < signedInfoBytes.length; i++) {
! sb.append((char)signedInfoBytes[i]);
}
! log.log(java.util.logging.Level.FINE, sb.toString());
! log.log(java.util.logging.Level.FINE, "Data to be signed/verified:" + Base64.encode(signedInfoBytes));
}
this.canonData = new ByteArrayInputStream(signedInfoBytes);
}
public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
! throws MarshalException
! {
ownerDoc = DOMUtils.getOwnerDocument(parent);
! Element siElem = DOMUtils.createElement(ownerDoc, "SignedInfo",
! XMLSignature.XMLNS, dsPrefix);
// create and append CanonicalizationMethod element
DOMCanonicalizationMethod dcm =
! (DOMCanonicalizationMethod)canonicalizationMethod;
dcm.marshal(siElem, dsPrefix, context);
// create and append SignatureMethod element
! ((DOMStructure)signatureMethod).marshal(siElem, dsPrefix, context);
// create and append Reference elements
! for (Reference reference : references) {
! ((DOMReference)reference).marshal(siElem, dsPrefix, context);
}
// append Id attribute
DOMUtils.setAttributeID(siElem, "Id", id);
parent.appendChild(siElem);
localSiElem = siElem;
}
+ @Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SignedInfo)) {
return false;
}
! SignedInfo osi = (SignedInfo)o;
! boolean idEqual = (id == null ? osi.getId() == null
! : id.equals(osi.getId()));
return (canonicalizationMethod.equals(osi.getCanonicalizationMethod())
&& signatureMethod.equals(osi.getSignatureMethod()) &&
references.equals(osi.getReferences()) && idEqual);
}
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ if (id != null) {
+ result = 31 * result + id.hashCode();
+ }
+ result = 31 * result + canonicalizationMethod.hashCode();
+ result = 31 * result + signatureMethod.hashCode();
+ result = 31 * result + references.hashCode();
+
+ return result;
+ }
}