You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ff...@apache.org on 2018/07/24 11:11:39 UTC

[camel] branch master updated: [CAMEL-12679]ensure camel-xmlsecurity can try key directly to decrypt message

This is an automated email from the ASF dual-hosted git repository.

ffang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new cb84ea2  [CAMEL-12679]ensure camel-xmlsecurity can try key directly to decrypt message
cb84ea2 is described below

commit cb84ea2e43ea0ae6e9ba937c02f3b8445ee0973d
Author: Freeman Fang <fr...@gmail.com>
AuthorDate: Tue Jul 24 19:11:23 2018 +0800

    [CAMEL-12679]ensure camel-xmlsecurity can try key directly to decrypt message
---
 .../xmlsecurity/XMLSecurityDataFormat.java         | 37 +++++++++++++++++++---
 .../camel/dataformat/xmlsecurity/TestHelper.java   | 13 ++++++++
 .../xmlsecurity/XMLSecurityDataFormatTest.java     | 29 +++++++++++++++++
 .../component/xmlsecurity/EncryptedMessage.xml     | 25 +++++++++++++++
 4 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java
index 1261df2..0e6d21d 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java
@@ -612,7 +612,18 @@ public class XMLSecurityDataFormat extends ServiceSupport implements DataFormat,
             keyEncryptionKey = generateKeyEncryptionKey("AES");
         }
 
-        return decode(exchange, encodedDocument, keyEncryptionKey);
+        Object ret = null;
+        try {
+            ret = decode(exchange, encodedDocument, keyEncryptionKey, true);
+        } catch (org.apache.xml.security.encryption.XMLEncryptionException ex) {
+            if (ex.getMessage().equals("encryption.nokey")) {
+                //the message don't have EncryptionKey, try key directly
+                ret = decode(exchange, encodedDocument, keyEncryptionKey, false);
+            } else {
+                throw ex;
+            }
+        }
+        return  ret;
     }
     
     private Object decodeWithAsymmetricKey(Exchange exchange, Document encodedDocument) throws Exception { 
@@ -628,14 +639,30 @@ public class XMLSecurityDataFormat extends ServiceSupport implements DataFormat,
         
         Key keyEncryptionKey = getPrivateKey(this.keyStore, this.recipientKeyAlias, 
                  this.keyPassword != null ? this.keyPassword : this.keyStorePassword);
-        return decode(exchange, encodedDocument, keyEncryptionKey);
+        Object ret = null;
+        try {
+            ret = decode(exchange, encodedDocument, keyEncryptionKey, true);
+        } catch (org.apache.xml.security.encryption.XMLEncryptionException ex) {
+            if (ex.getMessage().equals("encryption.nokey")) {
+                //the message don't have EncryptionKey, try key directly
+                ret = decode(exchange, encodedDocument, keyEncryptionKey, false);
+            } else {
+                throw ex;
+            }
+        }
+        return  ret;
     }
     
-    private Object decode(Exchange exchange, Document encodedDocument, Key keyEncryptionKey) throws Exception {
+    private Object decode(Exchange exchange, Document encodedDocument, Key keyEncryptionKey,
+                          boolean hasEncrytionKey) throws Exception {
         XMLCipher xmlCipher = XMLCipher.getInstance();
         xmlCipher.setSecureValidation(true);
-        xmlCipher.init(XMLCipher.DECRYPT_MODE, null);
-        xmlCipher.setKEK(keyEncryptionKey);
+        if (hasEncrytionKey) {
+            xmlCipher.init(XMLCipher.DECRYPT_MODE, null);
+            xmlCipher.setKEK(keyEncryptionKey);
+        } else {
+            xmlCipher.init(XMLCipher.DECRYPT_MODE, keyEncryptionKey);
+        }
 
         if (secureTag.equalsIgnoreCase("")) {
             checkEncryptionAlgorithm(keyEncryptionKey, encodedDocument.getDocumentElement());
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/TestHelper.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/TestHelper.java
index e23e16c..1d216e0 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/TestHelper.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/TestHelper.java
@@ -166,6 +166,19 @@ public class TestHelper {
         testDecryption(XML_FRAGMENT, context);
     }
     
+    protected void testDecryptionNoEncryptedKey(CamelContext context) throws Exception {
+        MockEndpoint resultEndpoint = context.getEndpoint("mock:decrypted", MockEndpoint.class);
+        resultEndpoint.setExpectedMessageCount(1);
+        context.start();
+        resultEndpoint.assertIsSatisfied(100);
+        Exchange exchange = resultEndpoint.getExchanges().get(0);
+        Document inDoc = getDocumentForInMessage(exchange);
+        XmlConverter converter = new XmlConverter();
+        String xmlStr = converter.toString(inDoc, exchange);
+        log.info(xmlStr);
+        Assert.assertFalse("The XML message has encrypted data.", hasEncryptedData(inDoc));
+    }
+    
     private boolean hasEncryptedData(Document doc) throws Exception {
         NodeList nodeList = doc.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData");
         return nodeList.getLength() > 0;
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java
index 24d3446..7a69370 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.dataformat.xmlsecurity;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -32,6 +33,7 @@ import org.apache.camel.converter.jaxp.XmlConverter;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.camel.util.jsse.KeyStoreParameters;
 import org.apache.xml.security.encryption.XMLCipher;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -165,6 +167,7 @@ public class XMLSecurityDataFormatTest extends CamelTestSupport {
         });
         xmlsecTestHelper.testEncryption(context);
     }
+    
 
     @Test
     public void testFullPayloadAsymmetricKeyEncryption() throws Exception {
@@ -342,6 +345,32 @@ public class XMLSecurityDataFormatTest extends CamelTestSupport {
         });
         xmlsecTestHelper.testDecryption(context);
     }
+    
+    @Test
+    public void testXMLElementDecryptionWithoutEncryptedKey() throws Exception {
+        if (!TestHelper.HAS_3DES) {
+            return;
+        }
+        String passPhrase = "this is a test passphrase";
+        
+        byte[] bytes = passPhrase.getBytes();
+        final byte[] keyBytes = Arrays.copyOf(bytes, 24);
+        for (int j = 0, k = 16; j < 8;) {
+            keyBytes[k++] = keyBytes[j++];
+        }
+
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("timer://foo?period=5000&repeatCount=1").
+                to("language:constant:resource:classpath:org/apache/camel/component/xmlsecurity/EncryptedMessage.xml")
+                .unmarshal()
+                        .secureXML("/*[local-name()='Envelope']/*[local-name()='Body']", 
+                                   true, keyBytes, XMLCipher.TRIPLEDES)
+                        .to("mock:decrypted");
+            }
+        });
+        xmlsecTestHelper.testDecryptionNoEncryptedKey(context);
+    }
 
     @Test
     public void testPartialPayloadXMLContentDecryptionWithKeyAndAlgorithm() throws Exception {
diff --git a/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/EncryptedMessage.xml b/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/EncryptedMessage.xml
new file mode 100644
index 0000000..74edc8a
--- /dev/null
+++ b/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/EncryptedMessage.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+  <S:Header>
+    <wsse:Security>
+      <xenc:ReferenceList>
+        <xenc:DataReference URI="StaticKeyEncryption" />
+      </xenc:ReferenceList>
+    </wsse:Security>
+  </S:Header>
+  <S:Body>
+    <xenc:EncryptedData Id="StaticKeyEncryption">
+      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc">
+        <KeySize>168</KeySize>
+      </xenc:EncryptionMethod>
+      <ds:KeyInfo>
+        <ds:KeyName>mykey</ds:KeyName>
+      </ds:KeyInfo>
+      <xenc:CipherData>
+        <xenc:CipherValue>yP17O2otQdraY+W42w8i8U/pQQac1g84vWaGWqbS1tgCduFfjhnIz2ZqbFJ6n7Ow1cIeF5HyAoHRGaoDd4gbVw==</xenc:CipherValue>
+      </xenc:CipherData>
+    </xenc:EncryptedData>
+  </S:Body>
+</S:Envelope>
+
+