You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by gi...@apache.org on 2014/10/26 15:25:41 UTC

svn commit: r1634334 - in /santuario/xml-security-java/trunk/src: main/java/org/apache/xml/security/stax/ext/ main/java/org/apache/xml/security/stax/impl/ main/java/org/apache/xml/security/stax/impl/processor/input/ test/java/org/apache/xml/security/te...

Author: giger
Date: Sun Oct 26 14:25:40 2014
New Revision: 1634334

URL: http://svn.apache.org/r1634334
Log:
more signature verification tests

Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/InputProcessorChain.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/InputProcessorChainImpl.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/input/XMLSecurityInputProcessor.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureVerificationTest.java

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/InputProcessorChain.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/InputProcessorChain.java?rev=1634334&r1=1634333&r2=1634334&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/InputProcessorChain.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/InputProcessorChain.java Sun Oct 26 14:25:40 2014
@@ -72,6 +72,7 @@ public interface InputProcessorChain ext
     /**
      * Create a new SubChain. The XMLEvents will be only be processed from the given InputProcessor to the end.
      * All earlier InputProcessors don't get these events. In other words the chain will be splitted in two parts.
+     * The associated DocumentContext will be cloned.
      *
      * @param inputProcessor The InputProcessor position the XMLEvents should be processed over this SubChain.
      * @return A new InputProcessorChain
@@ -81,6 +82,20 @@ public interface InputProcessorChain ext
     InputProcessorChain createSubChain(InputProcessor inputProcessor) throws XMLStreamException, XMLSecurityException;
 
     /**
+     * Create a new SubChain. The XMLEvents will be only be processed from the given InputProcessor to the end.
+     * All earlier InputProcessors don't get these events. In other words the chain will be splitted in two parts.
+     *
+     * The parameter clone controls if the associated DocumentContext should be cloned or reference the existing one.
+     *
+     * @param inputProcessor The InputProcessor position the XMLEvents should be processed over this SubChain.
+     * @param clone if true the associated DocumentContext will be cloned otherwise the DocumentContext will be referenced.
+     * @return A new InputProcessorChain
+     * @throws XMLStreamException   thrown when a streaming error occurs
+     * @throws XMLSecurityException thrown when a Security failure occurs
+     */
+    InputProcessorChain createSubChain(InputProcessor inputProcessor, boolean clone) throws XMLStreamException, XMLSecurityException;
+
+    /**
      * Requests the next security header XMLEvent from the next processor in the chain.
      *
      * @return The next XMLEvent from the previous processor

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/InputProcessorChainImpl.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/InputProcessorChainImpl.java?rev=1634334&r1=1634333&r2=1634334&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/InputProcessorChainImpl.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/InputProcessorChainImpl.java Sun Oct 26 14:25:40 2014
@@ -200,9 +200,15 @@ public class InputProcessorChainImpl imp
 
     @Override
     public InputProcessorChain createSubChain(InputProcessor inputProcessor) throws XMLStreamException, XMLSecurityException {
+        return createSubChain(inputProcessor, true);
+    }
+
+    @Override
+    public InputProcessorChain createSubChain(InputProcessor inputProcessor, boolean clone) throws XMLStreamException, XMLSecurityException {
         InputProcessorChainImpl inputProcessorChain;
         try {
-            inputProcessorChain = new InputProcessorChainImpl(inboundSecurityContext, documentContext.clone(),
+            final DocumentContextImpl docContext = clone ? documentContext.clone() : documentContext;
+            inputProcessorChain = new InputProcessorChainImpl(inboundSecurityContext, docContext,
                     inputProcessors.indexOf(inputProcessor) + 1, new ArrayList<InputProcessor>(this.inputProcessors));
         } catch (CloneNotSupportedException e) {
             throw new XMLSecurityException(e);

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/input/XMLSecurityInputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/input/XMLSecurityInputProcessor.java?rev=1634334&r1=1634333&r2=1634334&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/input/XMLSecurityInputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/input/XMLSecurityInputProcessor.java Sun Oct 26 14:25:40 2014
@@ -138,11 +138,15 @@ public class XMLSecurityInputProcessor e
                     inputProcessorChain.addProcessor(internalReplayProcessor);
 
                     //...and let the SignatureVerificationProcessor process the buffered events (enveloped signature).
-                    InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
+                    InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this, false);
                     while (!xmlSecEventList.isEmpty()) {
                         subInputProcessorChain.reset();
                         subInputProcessorChain.processEvent();
                     }
+
+                    // copy all processor back to main chain for finalization
+                    inputProcessorChain.getProcessors().clear();
+                    inputProcessorChain.getProcessors().addAll(subInputProcessorChain.getProcessors());
                 }
                 break;
         }

Modified: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureVerificationTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureVerificationTest.java?rev=1634334&r1=1634333&r2=1634334&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureVerificationTest.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureVerificationTest.java Sun Oct 26 14:25:40 2014
@@ -63,6 +63,7 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 /**
  * A set of test-cases for Signature verification.
@@ -1420,4 +1421,264 @@ public class SignatureVerificationTest e
 
         StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
     }
+
+    @Test
+    public void testPartialSignedDocumentTampered_ContentFirst() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument =
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+
+        // Set up the Key
+        KeyStore keyStore = KeyStore.getInstance("jks");
+        keyStore.load(
+                this.getClass().getClassLoader().getResource("transmitter.jks").openStream(),
+                "default".toCharArray()
+        );
+        Key key = keyStore.getKey("transmitter", "default".toCharArray());
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("transmitter");
+
+        // Sign using DOM
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        XMLSignature sig = signUsingDOM(
+                "http://www.w3.org/2000/09/xmldsig#rsa-sha1", document, localNames, key
+        );
+
+        // Add KeyInfo
+        sig.addKeyInfo(cert);
+
+        // Now modify the context of PaymentInfo
+        Element paymentInfoElement =
+                (Element)document.getElementsByTagNameNS("urn:example:po", "BillingAddress").item(0);
+        paymentInfoElement.setTextContent("Dig PLC, 1 First Ave, Dublin 1, US");
+
+        // Convert Document to a Stream Reader
+        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        transformer.transform(new DOMSource(document), new StreamResult(baos));
+        final XMLStreamReader xmlStreamReader =
+                xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
+
+        // Verify signature
+        XMLSecurityProperties properties = new XMLSecurityProperties();
+        InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
+        TestSecurityEventListener securityEventListener = new TestSecurityEventListener();
+        XMLStreamReader securityStreamReader =
+                inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);
+
+        try {
+            StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
+            fail("Failure expected on a modified document");
+        } catch (XMLStreamException ex) {
+            Assert.assertTrue(ex.getMessage().contains("Invalid digest of reference"));
+        }
+    }
+
+    @Test
+    public void testPartialSignedDocumentTampered_SignatureFirst() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument =
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+
+        // Set up the Key
+        KeyStore keyStore = KeyStore.getInstance("jks");
+        keyStore.load(
+                this.getClass().getClassLoader().getResource("transmitter.jks").openStream(),
+                "default".toCharArray()
+        );
+        Key key = keyStore.getKey("transmitter", "default".toCharArray());
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("transmitter");
+
+        // Sign using DOM
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        XMLSignature sig = signUsingDOM(
+                "http://www.w3.org/2000/09/xmldsig#rsa-sha1", document, localNames, key
+        );
+
+        // Add KeyInfo
+        sig.addKeyInfo(cert);
+
+        // Now modify the context of PaymentInfo
+        Element paymentInfoElement =
+                (Element)document.getElementsByTagNameNS("urn:example:po", "BillingAddress").item(0);
+        paymentInfoElement.setTextContent("Dig PLC, 1 First Ave, Dublin 1, US");
+
+        //move signature below root element
+        Element sigElement = (Element)document.getElementsByTagNameNS(
+                XMLSecurityConstants.TAG_dsig_Signature.getNamespaceURI(),
+                XMLSecurityConstants.TAG_dsig_Signature.getLocalPart()).item(0);
+        document.getDocumentElement().insertBefore(sigElement,
+                XMLUtils.getNextElement(document.getDocumentElement().getFirstChild()));
+
+        // Convert Document to a Stream Reader
+        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        transformer.transform(new DOMSource(document), new StreamResult(baos));
+        final XMLStreamReader xmlStreamReader =
+                xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
+
+        // Verify signature
+        XMLSecurityProperties properties = new XMLSecurityProperties();
+        InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
+        TestSecurityEventListener securityEventListener = new TestSecurityEventListener();
+        XMLStreamReader securityStreamReader =
+                inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);
+
+        try {
+            StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
+            fail("Failure expected on a modified document");
+        } catch (XMLStreamException ex) {
+            Assert.assertTrue(ex.getMessage().contains("Invalid digest of reference"));
+        }
+    }
+
+    @Test
+    public void testEnvelopedSignatureTampered_ContentFirst() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument =
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+
+        // Set up the Key
+        KeyStore keyStore = KeyStore.getInstance("jks");
+        keyStore.load(
+                this.getClass().getClassLoader().getResource("transmitter.jks").openStream(),
+                "default".toCharArray()
+        );
+        Key key = keyStore.getKey("transmitter", "default".toCharArray());
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("transmitter");
+
+        // Sign using DOM
+        List<String> localNames = new ArrayList<String>();
+
+        ReferenceInfo referenceInfo = new ReferenceInfo(
+                "",
+                new String[]{
+                        "http://www.w3.org/2000/09/xmldsig#enveloped-signature",
+                        "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
+                },
+                "http://www.w3.org/2000/09/xmldsig#sha1",
+                false
+        );
+
+        List<ReferenceInfo> referenceInfos = new ArrayList<ReferenceInfo>();
+        referenceInfos.add(referenceInfo);
+
+        XMLSignature sig = signUsingDOM(
+                "http://www.w3.org/2000/09/xmldsig#rsa-sha1", document, localNames, key, referenceInfos
+        );
+
+        // Add KeyInfo
+        sig.addKeyInfo(cert);
+
+        // Now modify the context of PaymentInfo
+        Element paymentInfoElement =
+                (Element)document.getElementsByTagNameNS("urn:example:po", "BillingAddress").item(0);
+        paymentInfoElement.setTextContent("Dig PLC, 1 First Ave, Dublin 1, US");
+
+        // Convert Document to a Stream Reader
+        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        transformer.transform(new DOMSource(document), new StreamResult(baos));
+        final XMLStreamReader xmlStreamReader =
+                xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
+
+        // Verify signature
+        XMLSecurityProperties properties = new XMLSecurityProperties();
+        InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
+        TestSecurityEventListener securityEventListener = new TestSecurityEventListener();
+        XMLStreamReader securityStreamReader =
+                inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);
+
+        try {
+            final Document res = StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
+            fail("Failure expected on a modified document");
+        } catch (XMLStreamException ex) {
+            Assert.assertTrue(ex.getMessage().contains("Invalid digest of reference"));
+        }
+    }
+
+    @Test
+    public void testEnvelopedSignatureTampered_SignatureFirst() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument =
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+
+        // Set up the Key
+        KeyStore keyStore = KeyStore.getInstance("jks");
+        keyStore.load(
+                this.getClass().getClassLoader().getResource("transmitter.jks").openStream(),
+                "default".toCharArray()
+        );
+        Key key = keyStore.getKey("transmitter", "default".toCharArray());
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("transmitter");
+
+        // Sign using DOM
+        List<String> localNames = new ArrayList<String>();
+
+        ReferenceInfo referenceInfo = new ReferenceInfo(
+                "",
+                new String[]{
+                        "http://www.w3.org/2000/09/xmldsig#enveloped-signature",
+                        "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
+                },
+                "http://www.w3.org/2000/09/xmldsig#sha1",
+                false
+        );
+
+        List<ReferenceInfo> referenceInfos = new ArrayList<ReferenceInfo>();
+        referenceInfos.add(referenceInfo);
+
+        XMLSignature sig = signUsingDOM(
+                "http://www.w3.org/2000/09/xmldsig#rsa-sha1", document, localNames, key, referenceInfos
+        );
+
+        // Add KeyInfo
+        sig.addKeyInfo(cert);
+
+        // Now modify the context of PaymentInfo
+        Element paymentInfoElement =
+                (Element)document.getElementsByTagNameNS("urn:example:po", "BillingAddress").item(0);
+        paymentInfoElement.setTextContent("Dig PLC, 1 First Ave, Dublin 1, US");
+
+        //move signature below root element
+        Element sigElement = (Element)document.getElementsByTagNameNS(
+                XMLSecurityConstants.TAG_dsig_Signature.getNamespaceURI(),
+                XMLSecurityConstants.TAG_dsig_Signature.getLocalPart()).item(0);
+        document.getDocumentElement().insertBefore(sigElement,
+                XMLUtils.getNextElement(document.getDocumentElement().getFirstChild()));
+
+        // Convert Document to a Stream Reader
+        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        transformer.transform(new DOMSource(document), new StreamResult(baos));
+        final XMLStreamReader xmlStreamReader =
+                xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
+
+        // Verify signature
+        XMLSecurityProperties properties = new XMLSecurityProperties();
+        InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
+        TestSecurityEventListener securityEventListener = new TestSecurityEventListener();
+        XMLStreamReader securityStreamReader =
+                inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);
+
+        try {
+            final Document res = StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
+            fail("Failure expected on a modified document");
+        } catch (XMLStreamException ex) {
+            Assert.assertTrue(ex.getMessage().contains("Invalid digest of reference"));
+        }
+    }
 }