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"));
+ }
+ }
}