src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java
changeset 50614 3810c9a2efa1
parent 47216 71c04702a3d5
child 59240 b3116877866f
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java	Mon Jun 18 15:24:48 2018 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java	Tue Jun 19 08:06:35 2018 +0800
@@ -27,20 +27,19 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
-import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase;
+import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments;
 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315OmitComments;
-import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments;
+import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase;
 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException;
 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
@@ -51,7 +50,6 @@
 /**
  * Class XMLSignatureInput
  *
- * @author Christian Geuer-Pollmann
  * $todo$ check whether an XMLSignatureInput can be _both_, octet stream _and_ node set?
  */
 public class XMLSignatureInput {
@@ -68,19 +66,19 @@
      * Some InputStreams do not support the {@link java.io.InputStream#reset}
      * method, so we read it in completely and work on our Proxy.
      */
-    private InputStream inputOctetStreamProxy = null;
+    private InputStream inputOctetStreamProxy;
     /**
      * The original NodeSet for this XMLSignatureInput
      */
-    private Set<Node> inputNodeSet = null;
+    private Set<Node> inputNodeSet;
     /**
      * The original Element
      */
-    private Node subNode = null;
+    private Node subNode;
     /**
      * Exclude Node *for enveloped transformations*
      */
-    private Node excludeNode = null;
+    private Node excludeNode;
     /**
      *
      */
@@ -90,7 +88,8 @@
     /**
      * A cached bytes
      */
-    private byte[] bytes = null;
+    private byte[] bytes;
+    private boolean secureValidation;
 
     /**
      * Some Transforms may require explicit MIME type, charset (IANA registered
@@ -101,22 +100,25 @@
      * Transform algorithm and should be described in the specification for the
      * algorithm.
      */
-    private String mimeType = null;
+    private String mimeType;
 
     /**
      * Field sourceURI
      */
-    private String sourceURI = null;
+    private String sourceURI;
 
     /**
      * Node Filter list.
      */
-    private List<NodeFilter> nodeFilters = new ArrayList<NodeFilter>();
+    private List<NodeFilter> nodeFilters = new ArrayList<>();
 
     private boolean needsToBeExpanded = false;
-    private OutputStream outputStream = null;
+    private OutputStream outputStream;
 
-    private DocumentBuilderFactory dfactory;
+    /**
+     * Pre-calculated digest value of the object in base64.
+     */
+    private String preCalculatedDigest;
 
     /**
      * Construct a XMLSignatureInput from an octet array.
@@ -132,7 +134,7 @@
     }
 
     /**
-     * Constructs a <code>XMLSignatureInput</code> from an octet stream. The
+     * Constructs a {@code XMLSignatureInput} from an octet stream. The
      * stream is directly read.
      *
      * @param inputOctetStream
@@ -161,6 +163,15 @@
     }
 
     /**
+     * Construct a {@code XMLSignatureInput} from a known digest value in Base64.
+     * This makes it possible to compare the element digest with the provided digest value.
+     * @param preCalculatedDigest digest value in base64.
+     */
+    public XMLSignatureInput(String preCalculatedDigest) {
+        this.preCalculatedDigest = preCalculatedDigest;
+    }
+
+    /**
      * Check if the structure needs to be expanded.
      * @return true if so.
      */
@@ -286,8 +297,7 @@
      * @return true if the object has been set up with a Node set
      */
     public boolean isNodeSet() {
-        return ((inputOctetStreamProxy == null
-            && inputNodeSet != null) || isNodeSet);
+        return inputOctetStreamProxy == null && inputNodeSet != null || isNodeSet;
     }
 
     /**
@@ -296,8 +306,8 @@
      * @return true if the object has been set up with an Element
      */
     public boolean isElement() {
-        return (inputOctetStreamProxy == null && subNode != null
-            && inputNodeSet == null && !isNodeSet);
+        return inputOctetStreamProxy == null && subNode != null
+            && inputNodeSet == null && !isNodeSet;
     }
 
     /**
@@ -306,8 +316,8 @@
      * @return true if the object has been set up with an octet stream
      */
     public boolean isOctetStream() {
-        return ((inputOctetStreamProxy != null || bytes != null)
-          && (inputNodeSet == null && subNode == null));
+        return (inputOctetStreamProxy != null || bytes != null)
+          && inputNodeSet == null && subNode == null;
     }
 
     /**
@@ -327,7 +337,15 @@
      * @return true is the object has been set up with an octet stream
      */
     public boolean isByteArray() {
-        return (bytes != null && (this.inputNodeSet == null && subNode == null));
+        return bytes != null && this.inputNodeSet == null && subNode == null;
+    }
+
+    /**
+     * Determines if the object has been set up with a pre-calculated digest.
+     * @return
+     */
+    public boolean isPreCalculatedDigest() {
+        return preCalculatedDigest != null;
     }
 
     /**
@@ -377,7 +395,7 @@
 
     /**
      * Method toString
-     * @inheritDoc
+     * {@inheritDoc}
      */
     public String toString() {
         if (isNodeSet()) {
@@ -556,13 +574,7 @@
 
     void convertToNodes() throws CanonicalizationException,
         ParserConfigurationException, IOException, SAXException {
-        if (dfactory == null) {
-            dfactory = DocumentBuilderFactory.newInstance();
-            dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
-            dfactory.setValidating(false);
-            dfactory.setNamespaceAware(true);
-        }
-        DocumentBuilder db = dfactory.newDocumentBuilder();
+        DocumentBuilder db = XMLUtils.createDocumentBuilder(false, secureValidation);
         // select all nodes, also the comments.
         try {
             db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler());
@@ -570,16 +582,20 @@
             Document doc = db.parse(this.getOctetStream());
             this.subNode = doc;
         } catch (SAXException ex) {
+            byte[] result = null;
             // if a not-wellformed nodeset exists, put a container around it...
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
 
-            baos.write("<container>".getBytes("UTF-8"));
-            baos.write(this.getBytes());
-            baos.write("</container>".getBytes("UTF-8"));
+                baos.write("<container>".getBytes(StandardCharsets.UTF_8));
+                baos.write(this.getBytes());
+                baos.write("</container>".getBytes(StandardCharsets.UTF_8));
 
-            byte result[] = baos.toByteArray();
-            Document document = db.parse(new ByteArrayInputStream(result));
-            this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
+                result = baos.toByteArray();
+            }
+            try (InputStream is = new ByteArrayInputStream(result)) {
+                Document document = db.parse(is);
+                this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
+            }
         } finally {
             if (this.inputOctetStreamProxy != null) {
                 this.inputOctetStreamProxy.close();
@@ -589,4 +605,15 @@
         }
     }
 
+    public boolean isSecureValidation() {
+        return secureValidation;
+    }
+
+    public void setSecureValidation(boolean secureValidation) {
+        this.secureValidation = secureValidation;
+    }
+
+    public String getPreCalculatedDigest() {
+        return preCalculatedDigest;
+    }
 }