Repository: camel Updated Branches: refs/heads/master a342ef7df -> afd273710
CAMEL-9306: XML Signature: Header for Transform Methods Change-Id: I0a313c24841dd806f1a13f9daec1cf85f9142a4e Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/afd27371 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/afd27371 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/afd27371 Branch: refs/heads/master Commit: afd273710f5487162b83f72ef071cf1716858373 Parents: a342ef7 Author: Franz Forsthofer <franz.forstho...@sap.com> Authored: Tue Nov 10 13:39:12 2015 +0100 Committer: Franz Forsthofer <franz.forstho...@sap.com> Committed: Tue Nov 10 13:43:28 2015 +0100 ---------------------------------------------------------------------- .../xmlsecurity/api/XmlSignatureConstants.java | 14 +++++ .../processor/XmlSignerProcessor.java | 60 ++++++++++++-------- .../component/xmlsecurity/XmlSignatureTest.java | 22 ++++++- 3 files changed, 72 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/afd27371/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureConstants.java ---------------------------------------------------------------------- diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureConstants.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureConstants.java index 5fecbcf..1b65c2d 100644 --- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureConstants.java +++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureConstants.java @@ -61,6 +61,20 @@ public final class XmlSignatureConstants { public static final String HEADER_SCHEMA_RESOURCE_URI = "CamelXmlSignatureSchemaResourceUri"; public static final String HEADER_XPATHS_TO_ID_ATTRIBUTES = "CamelXmlSignatureXpathsToIdAttributes"; + + /** + * Header for dynamic specifying the transform methods of the reference to the + * signed data. The value of the header must be a comma separated list with + * the transform algorithms, for example: + * "http://www.w3.org/2000/09/xmldsig#enveloped-signature,http://www.w3.org/TR/2001/REC-xml-c14n-20010315" + * <p> + * Used for the XML signer. This header will overwrite the configuration + * property "transformMethods". You cannot use transform algorithms, which + * need parameters like http://www.w3.org/TR/1999/REC-xslt-19991116, + * http://www.w3.org/2002/06/xmldsig-filter2, or + * http://www.w3.org/TR/1999/REC-xpath-19991116. + */ + public static final String HEADER_TRANSFORM_METHODS = "CamelXmlSignatureTransformMethods"; /*------------------------- headers for XAdES signer ----------------------------------------------------------*/ /** http://git-wip-us.apache.org/repos/asf/camel/blob/afd27371/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java index 0122b45..8a7f567 100644 --- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java +++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java @@ -569,7 +569,7 @@ public class XmlSignerProcessor extends XmlSignatureProcessor { String referenceId = properties == null ? null : properties.getContentReferenceId(); // Create Reference with URI="#<objectId>" for enveloping signature, URI="" for enveloped signature, and URI = <value from configuration> for detached signature and the transforms Reference ref = createReference(input.getSignatureFactory(), input.getContentReferenceUri(), - getContentReferenceType(input.getMessage()), input.getSignatureType(), referenceId); + getContentReferenceType(input.getMessage()), input.getSignatureType(), referenceId, input.getMessage()); Reference keyInfoRef = createKeyInfoReference(input.getSignatureFactory(), keyInfoId, input.getContentDigestAlgorithm()); int propsRefsSize = properties == null || properties.getReferences() == null || properties.getReferences().isEmpty() ? 0 @@ -646,10 +646,10 @@ public class XmlSignerProcessor extends XmlSignatureProcessor { } } - protected Reference createReference(XMLSignatureFactory fac, String uri, String type, SignatureType sigType, String id) + protected Reference createReference(XMLSignatureFactory fac, String uri, String type, SignatureType sigType, String id, Message message) throws InvalidAlgorithmParameterException, XmlSignatureException { try { - List<Transform> transforms = getTransforms(fac, sigType); + List<Transform> transforms = getTransforms(fac, sigType, message); Reference ref = fac.newReference(uri, fac.newDigestMethod(getDigestAlgorithmUri(), null), transforms, type, id); return ref; } catch (NoSuchAlgorithmException e) { @@ -766,32 +766,46 @@ public class XmlSignerProcessor extends XmlSignatureProcessor { return fac.newXMLObject(Collections.singletonList(new DOMStructure(node)), id, null, null); } - private List<Transform> getTransforms(XMLSignatureFactory fac, SignatureType sigType) throws NoSuchAlgorithmException, + private List<Transform> getTransforms(XMLSignatureFactory fac, SignatureType sigType, Message message) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { - List<AlgorithmMethod> configuredTrafos = getConfiguration().getTransformMethods(); - if (SignatureType.enveloped == sigType) { - // add enveloped transform if necessary - if (configuredTrafos.size() > 0) { - if (!containsEnvelopedTransform(configuredTrafos)) { - configuredTrafos = new ArrayList<AlgorithmMethod>(configuredTrafos.size() + 1); + String transformMethodsHeaderValue = message.getHeader(XmlSignatureConstants.HEADER_TRANSFORM_METHODS, String.class); + if (transformMethodsHeaderValue == null) { + List<AlgorithmMethod> configuredTrafos = getConfiguration().getTransformMethods(); + if (SignatureType.enveloped == sigType) { + // add enveloped transform if necessary + if (configuredTrafos.size() > 0) { + if (!containsEnvelopedTransform(configuredTrafos)) { + configuredTrafos = new ArrayList<AlgorithmMethod>(configuredTrafos.size() + 1); + configuredTrafos.add(XmlSignatureHelper.getEnvelopedTransform()); + configuredTrafos.addAll(getConfiguration().getTransformMethods()); + } + } else { + // add enveloped and C14N trafo + configuredTrafos = new ArrayList<AlgorithmMethod>(2); configuredTrafos.add(XmlSignatureHelper.getEnvelopedTransform()); - configuredTrafos.addAll(getConfiguration().getTransformMethods()); + configuredTrafos.add(XmlSignatureHelper.getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE)); } - } else { - // add enveloped and C14N trafo - configuredTrafos = new ArrayList<AlgorithmMethod>(2); - configuredTrafos.add(XmlSignatureHelper.getEnvelopedTransform()); - configuredTrafos.add(XmlSignatureHelper.getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE)); } - } - List<Transform> transforms = new ArrayList<Transform>(configuredTrafos.size()); - for (AlgorithmMethod trafo : configuredTrafos) { - Transform transform = fac.newTransform(trafo.getAlgorithm(), (TransformParameterSpec) trafo.getParameterSpec()); - transforms.add(transform); - LOG.debug("Transform method: {}", trafo.getAlgorithm()); + List<Transform> transforms = new ArrayList<Transform>(configuredTrafos.size()); + for (AlgorithmMethod trafo : configuredTrafos) { + Transform transform = fac.newTransform(trafo.getAlgorithm(), (TransformParameterSpec) trafo.getParameterSpec()); + transforms.add(transform); + LOG.debug("Transform method: {}", trafo.getAlgorithm()); + } + return transforms; + } else { + LOG.debug("Header {} with value '{}' found", XmlSignatureConstants.HEADER_TRANSFORM_METHODS, transformMethodsHeaderValue); + String[] transformAlgorithms = transformMethodsHeaderValue.split(","); + List<Transform> transforms = new ArrayList<Transform>(transformAlgorithms.length); + for (String transformAlgorithm : transformAlgorithms) { + transformAlgorithm = transformAlgorithm.trim(); + Transform transform = fac.newTransform(transformAlgorithm, (TransformParameterSpec) null); + transforms.add(transform); + LOG.debug("Transform method: {}", transformAlgorithm); + } + return transforms; } - return transforms; } private boolean containsEnvelopedTransform(List<AlgorithmMethod> configuredTrafos) { http://git-wip-us.apache.org/repos/asf/camel/blob/afd27371/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java ---------------------------------------------------------------------- diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java index fa62b2e..cd1d2c9 100644 --- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java +++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java @@ -386,6 +386,14 @@ public class XmlSignatureTest extends CamelTestSupport { sendBody("direct:enveloping", payload); assertMockEndpointsSatisfied(); } + + @Test + public void testEnvelopedSignatureWithTransformHeader() throws Exception { + setupMock(payload); + sendBody("direct:enveloped", payload, Collections.<String, Object>singletonMap(XmlSignatureConstants.HEADER_TRANSFORM_METHODS, + "http://www.w3.org/2000/09/xmldsig#enveloped-signature,http://www.w3.org/TR/2001/REC-xml-c14n-20010315")); + assertMockEndpointsSatisfied(); + } @Test public void testEnvelopingSignatureWithPlainText() throws Exception { @@ -808,6 +816,12 @@ public class XmlSignatureTest extends CamelTestSupport { public void testDetachedSignature() throws Exception { testDetachedSignatureInternal(); } + + @Test + public void testDetachedSignatureWitTransformHeader() throws Exception { + testDetachedSignatureInternal(Collections.singletonMap(XmlSignatureConstants.HEADER_TRANSFORM_METHODS, + (Object)"http://www.w3.org/2000/09/xmldsig#enveloped-signature,http://www.w3.org/TR/2001/REC-xml-c14n-20010315")); + } @Test public void testSignatureIdAtributeNull() throws Exception { @@ -842,6 +856,12 @@ public class XmlSignatureTest extends CamelTestSupport { private Element testDetachedSignatureInternal() throws InterruptedException, XPathExpressionException, SAXException, IOException, ParserConfigurationException { + return testDetachedSignatureInternal(Collections.<String, Object>emptyMap()); + } + + private Element testDetachedSignatureInternal(Map<String, Object> headers) throws InterruptedException, XPathExpressionException, SAXException, IOException, + ParserConfigurationException { + String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + (includeNewLine ? "\n" : "") + "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>"; @@ -849,7 +869,7 @@ public class XmlSignatureTest extends CamelTestSupport { mock.expectedMessageCount(1); MockEndpoint mockVerified = getMockEndpoint("mock:verified"); mockVerified.expectedBodiesReceived(detachedPayload); - sendBody("direct:detached", detachedPayload); + sendBody("direct:detached", detachedPayload, headers); assertMockEndpointsSatisfied(); Map<String, String> namespaceMap = new TreeMap<String, String>(); namespaceMap.put("ns", "http://test");