You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ha...@apache.org on 2011/06/21 04:42:46 UTC

svn commit: r1137849 - in /camel/branches/camel-2.7.x: ./ components/camel-http/ components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/ components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/ com...

Author: hadrian
Date: Tue Jun 21 02:42:46 2011
New Revision: 1137849

URL: http://svn.apache.org/viewvc?rev=1137849&view=rev
Log:
CAMEL-4061. Port to the 2.7.x branch

Added:
    camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/recipient.ks
      - copied unchanged from r1135364, camel/trunk/components/camel-xmlsecurity/src/test/resources/recipient.ks
    camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/sender.ts
      - copied unchanged from r1135364, camel/trunk/components/camel-xmlsecurity/src/test/resources/sender.ts
Modified:
    camel/branches/camel-2.7.x/   (props changed)
    camel/branches/camel-2.7.x/components/camel-http/   (props changed)
    camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java
    camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java
    camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/log4j.properties

Propchange: camel/branches/camel-2.7.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jun 21 02:42:46 2011
@@ -1 +1 @@
-/camel/trunk:1083696,1087276,1087612,1087856,1088583,1088916-1088917,1089275,1090166,1091518,1091771,1091799,1092068,1092577,1092667,1093978,1095405,1095469,1095471,1095475-1095476,1099417,1102162,1104076,1124497,1131411,1134501
+/camel/trunk:1083696,1087276,1087612,1087856,1088583,1088916-1088917,1089275,1090166,1091518,1091771,1091799,1092068,1092577,1092667,1093978,1095405,1095469,1095471,1095475-1095476,1099417,1102162,1104076,1124497,1131411,1134501,1135364

Propchange: camel/branches/camel-2.7.x/components/camel-http/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jun 21 02:42:46 2011
@@ -1 +1 @@
-/camel/trunk/components/camel-http:917526,1083696,1087276,1087612,1087856,1088583,1088916-1088917,1089275,1090166,1091518,1091771,1091799,1092068,1092577,1092667,1093978,1095405,1095469,1095471,1095475-1095476,1099417,1102162,1104076,1124497,1131411,1134501
+/camel/trunk/components/camel-http:917526,1083696,1087276,1087612,1087856,1088583,1088916-1088917,1089275,1090166,1091518,1091771,1091799,1092068,1092577,1092667,1093978,1095405,1095469,1095471,1095475-1095476,1099417,1102162,1104076,1124497,1131411,1134501,1135364

Modified: camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java?rev=1137849&r1=1137848&r2=1137849&view=diff
==============================================================================
--- camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java (original)
+++ camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java Tue Jun 21 02:42:46 2011
@@ -19,11 +19,18 @@ package org.apache.camel.dataformat.xmls
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.URL;
 import java.security.InvalidKeyException;
 import java.security.Key;
+import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
+import java.util.Map;
+
+import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.DESedeKeySpec;
 import javax.crypto.spec.SecretKeySpec;
@@ -32,8 +39,11 @@ import javax.xml.transform.dom.DOMSource
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 import org.w3c.dom.traversal.NodeIterator;
 
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.util.ExchangeHelper;
@@ -45,11 +55,31 @@ import org.apache.xml.security.encryptio
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xpath.XPathAPI;
 
-public class XMLSecurityDataFormat implements DataFormat {
+public class XMLSecurityDataFormat implements DataFormat, CamelContextAware {
+
+    public static final String XML_ENC_RECIPIENT_ALIAS = "CamelXmlEncryptionRecipientAlias";
+    public static final String XML_ENC_TRUST_STORE_URL = "CamelXmlEncryptionTrustStoreUrl";
+    public static final String XML_ENC_TRUST_STORE_PASSWORD = "CamelXmlEncryptionTrustStorePassword";
+    public static final String XML_ENC_KEY_STORE_URL = "CamelXmlEncryptionKeyStoreUrl";
+    public static final String XML_ENC_KEY_STORE_PASSWORD = "CamelXmlEncryptionKeyStorePassword";
+    public static final String XML_ENC_KEY_STORE_ALIAS = "CamelXmlEncryptionKeyAlias";
+
     private String xmlCipherAlgorithm;
+    private String keyCipherAlgorithm;
     private byte[] passPhrase;
+
     private String secureTag;
     private boolean secureTagContents;
+    
+    private KeyStore keyStore;
+    private KeyStore trustStore;
+    private String keyStoreAlias;
+    private String keyStorePassword;
+    private String trustStorePassword;
+    private String recipientKeyAlias;
+    
+    private CamelContext camelContext;
+        
 
     public XMLSecurityDataFormat() {
         this.xmlCipherAlgorithm = XMLCipher.TRIPLEDES;
@@ -73,45 +103,197 @@ public class XMLSecurityDataFormat imple
         this.setPassPhrase(passPhrase);
     }
 
-    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, byte[] passPhrase, String xmlCipherAlgorithm) {
+    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, byte[] passPhrase, 
+                                 String xmlCipherAlgorithm) {
         this();
         this.setSecureTag(secureTag);
         this.setSecureTagContents(secureTagContents);
         this.setPassPhrase(passPhrase);
         this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
     }
+    
+    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String xmlCipherAlgorithm, 
+            String keyCipherAlgorithm) {
+        this();
+        this.setSecureTag(secureTag);
+        this.setSecureTagContents(secureTagContents);
+        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
+        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
+    }
+      
+    public XMLSecurityDataFormat(String secureTag, boolean secureTagContents, String recipientKeyAlias, 
+                                 String xmlCipherAlgorithm, String keyCipherAlgorithm) {
+        this();
+        this.setSecureTag(secureTag);
+        this.setSecureTagContents(secureTagContents);
+        this.setXmlCipherAlgorithm(xmlCipherAlgorithm);
+        this.setRecipientKeyAlias(recipientKeyAlias);
+        this.setKeyCipherAlgorithm(keyCipherAlgorithm);
+    }
+    
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        try {
+            setDefaultsFromContext(camelContext);
+        } catch (Exception e) {
+            throw new IllegalStateException("Could not initialize XMLSecurityDataFormat with camelContext. ", e);
+        }
+    }
 
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+    
+    /**
+     * Sets missing properties that are defined in the Camel context.
+     */
+    private void setDefaultsFromContext(CamelContext context) throws Exception {
+        Map<String, String> contextProps = context.getProperties();
+        
+        if (this.recipientKeyAlias == null) {
+            recipientKeyAlias = contextProps.get(XML_ENC_RECIPIENT_ALIAS);
+        }
+        
+        if (this.trustStore == null && contextProps.containsKey(XML_ENC_TRUST_STORE_URL)) {
+            trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            URL trustStoreUrl = new URL(contextProps.get(XML_ENC_TRUST_STORE_URL));
+            if (trustStorePassword == null) {
+                trustStorePassword = contextProps.get(XML_ENC_TRUST_STORE_PASSWORD);
+            }
+            trustStore.load(trustStoreUrl.openStream(), trustStorePassword.toCharArray());
+        }
+        
+        if (this.keyStore == null && contextProps.containsKey(XML_ENC_KEY_STORE_URL)) {
+            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            URL keyStoreUrl = new URL(contextProps.get(XML_ENC_KEY_STORE_URL));
+            if (keyStorePassword == null) {
+                keyStorePassword = contextProps.get(XML_ENC_KEY_STORE_PASSWORD);
+            }
+            keyStore.load(keyStoreUrl.openStream(), keyStorePassword.toCharArray());
+        }
+        
+        if (this.keyStoreAlias == null) {
+            keyStoreAlias = contextProps.get(XML_ENC_KEY_STORE_ALIAS);
+        }
+    }
+    
     public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
-
         // Retrieve the message body as input stream
         InputStream is = exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class, graph);
         // and covert that to XML
         Document document = exchange.getContext().getTypeConverter().convertTo(Document.class, exchange, is);
+        
+        if (null != keyCipherAlgorithm 
+            && (keyCipherAlgorithm.equals(XMLCipher.RSA_v1dot5) || keyCipherAlgorithm.equals(XMLCipher.RSA_OAEP))) {
+            encryptAsymmetric(exchange, document, stream);
+        } else if (null != recipientKeyAlias) {
+            encryptAsymmetric(exchange, document, stream);
+        } else {
+            encryptSymmetric(exchange, document, stream);
+        }
+    }
+    
+    /**
+     * Configure the public key for the asymmetric key wrap algorithm, create the key cipher, and delegate
+     * to common encryption method.
+     * 
+     * The method first checks the exchange for a declared key alias, and will fall back to the
+     * statically-defined instance variable if no value is found in the exchange. This allows different
+     * aliases / keys to be used for multiple-recipient messaging integration patterns such as CBR
+     * or recipient list.
+     */
+    private void encryptAsymmetric(Exchange exchange, Document document, OutputStream stream) throws Exception {       
+        String exchangeRecipientAlias = getRecipientKeyAlias(exchange);
+        
+        if (null == exchangeRecipientAlias) {
+            throw new IllegalStateException("The  recipient's key alias must be defined for asymmetric key encryption.");
+        }
 
-        Key keyEncryptionkey;
-        Key dataEncryptionkey;
+        if (null == trustStore) {
+            throw new IllegalStateException("A trust store must be defined for asymmetric key encryption.");
+        }
+        
+        Key keyEncryptionKey = getPublicKey(this.trustStore, exchangeRecipientAlias, this.trustStorePassword);
+        
+        if (null == keyEncryptionKey) {
+            throw new IllegalStateException("No key for the alias [ " + exchangeRecipientAlias 
+                + " ] exists in " + "the configured trust store.");
+        }
+        
+        Key dataEncryptionKey = generateDataEncryptionKey();
+        
+        XMLCipher keyCipher;
+        if (null != this.getKeyCyperAlgorithm()) {
+            keyCipher = XMLCipher.getInstance(this.getKeyCyperAlgorithm());
+        } else {
+            keyCipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
+        }
+        keyCipher.init(XMLCipher.WRAP_MODE, keyEncryptionKey);
+        encrypt(exchange, document, stream, dataEncryptionKey, keyCipher);
+    }
+     
+    private void encryptSymmetric(Exchange exchange, Document document, OutputStream stream) throws Exception {
+        Key keyEncryptionKey;
+        Key dataEncryptionKey;
         if (xmlCipherAlgorithm.equals(XMLCipher.TRIPLEDES)) {
-            keyEncryptionkey = generateEncryptionKey("DESede");
-            dataEncryptionkey = generateEncryptionKey("DESede");
+            keyEncryptionKey = generateKeyEncryptionKey("DESede");
+            dataEncryptionKey = generateDataEncryptionKey();
         } else {
-            keyEncryptionkey = generateEncryptionKey("AES");
-            dataEncryptionkey = generateEncryptionKey("AES");
+            keyEncryptionKey = generateKeyEncryptionKey("AES");
+            dataEncryptionKey = generateDataEncryptionKey();
         }
-
+        
         XMLCipher keyCipher = XMLCipher.getInstance(generateXmlCipherAlgorithmKeyWrap());
-        keyCipher.init(XMLCipher.WRAP_MODE, keyEncryptionkey);
-
+        keyCipher.init(XMLCipher.WRAP_MODE, keyEncryptionKey);
+        
+        encrypt(exchange, document, stream, dataEncryptionKey, keyCipher);
+    }
+    
+    
+    /**
+     * Returns the private key for the specified alias, or null if the alias or private key is not found.
+     */
+    // TODO Move this to a crypto utility class
+    private Key getPrivateKey(KeyStore keystore, String alias, String password) throws Exception {
+        Key key = keystore.getKey(alias, password.toCharArray());
+        if (key instanceof PrivateKey) {
+            return key;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Returns the public key for the specified alias, or null if the alias or private key is not found.
+     */    
+    // TODO Move this to a crypto utility class
+    private Key getPublicKey(KeyStore keystore, String alias, String password) throws Exception {
+        Key key = keystore.getKey(alias, password.toCharArray());
+        if (key instanceof PublicKey) {
+            return key;
+        } else {
+            java.security.cert.Certificate cert = keystore.getCertificate(alias);
+            // Get public key
+            PublicKey publicKey = cert.getPublicKey();
+            return publicKey;
+        }
+    }
+ 
+    
+    private void encrypt(Exchange exchange, Document document, OutputStream stream, Key dataEncryptionKey, 
+                         XMLCipher keyCipher) throws Exception {
         XMLCipher xmlCipher = XMLCipher.getInstance(xmlCipherAlgorithm);
-        xmlCipher.init(XMLCipher.ENCRYPT_MODE, dataEncryptionkey);
+        xmlCipher.init(XMLCipher.ENCRYPT_MODE, dataEncryptionKey);
 
         if (secureTag.equalsIgnoreCase("")) {
-            embedKeyInfoInEncryptedData(document, keyCipher, xmlCipher, dataEncryptionkey);
+            embedKeyInfoInEncryptedData(document, keyCipher, xmlCipher, dataEncryptionKey);
             document = xmlCipher.doFinal(document, document.getDocumentElement());
         } else {
             NodeIterator iter = XPathAPI.selectNodeIterator(document, secureTag);
             Node node;
             while ((node = iter.nextNode()) != null) {
-                embedKeyInfoInEncryptedData(document, keyCipher, xmlCipher, dataEncryptionkey);
+                embedKeyInfoInEncryptedData(document, keyCipher, xmlCipher, dataEncryptionKey);
                 Document temp = xmlCipher.doFinal(document, (Element) node, getSecureTagContents());
                 document.importNode(temp.getDocumentElement().cloneNode(true), true);
             }
@@ -124,37 +306,74 @@ public class XMLSecurityDataFormat imple
         } finally {
             stream.close();
         }
-
     }
-
-    public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
+    
+    public Object unmarshal(Exchange exchange, Document document) throws Exception {
         InputStream is = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
-
-        Key keyEncryptionkey;
+        return unmarshal(exchange, is);
+    }
+    
+    
+    @Override
+    public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
+        Document encodedDocument = exchange.getContext().getTypeConverter().convertTo(Document.class, exchange, stream);        
+        
+        if (null != keyCipherAlgorithm 
+            && (keyCipherAlgorithm.equals(XMLCipher.RSA_v1dot5) || keyCipherAlgorithm.equals(XMLCipher.RSA_OAEP))) {
+            return decodeWithAsymmetricKey(exchange, encodedDocument);
+        } else {
+            return decodeWithSymmetricKey(exchange, encodedDocument);
+        }
+    }
+    
+    private Object decodeWithSymmetricKey(Exchange exchange, Document encodedDocument) throws Exception {
+        Key keyEncryptionKey;
         if (xmlCipherAlgorithm.equals(XMLCipher.TRIPLEDES)) {
-            keyEncryptionkey = generateEncryptionKey("DESede");
+            keyEncryptionKey = generateKeyEncryptionKey("DESede");
         } else {
-            keyEncryptionkey = generateEncryptionKey("AES");
+            keyEncryptionKey = generateKeyEncryptionKey("AES");
         }
 
+        return decode(exchange, encodedDocument, keyEncryptionKey);
+    }
+    
+    private Object decodeWithAsymmetricKey(Exchange exchange, Document encodedDocument) throws Exception {        
+        if (this.keyStore ==  null) {
+            throw new IllegalStateException("A key store must be defined for asymmetric key decryption.");
+        }
+        
+        Key keyEncryptionKey = getPrivateKey(this.keyStore, this.keyStoreAlias, this.keyStorePassword);
+        return decode(exchange, encodedDocument, keyEncryptionKey);
+    }
+    
+    private Object decode(Exchange exchange, Document encodedDocument, Key keyEncryptionKey) throws Exception {
         XMLCipher xmlCipher = XMLCipher.getInstance();
         xmlCipher.init(XMLCipher.DECRYPT_MODE, null);
-        xmlCipher.setKEK(keyEncryptionkey);
-
-        Document encodedDocument = exchange.getContext().getTypeConverter().convertTo(Document.class, exchange, is);
+        xmlCipher.setKEK(keyEncryptionKey);
 
         if (secureTag.equalsIgnoreCase("")) {
             encodedDocument = xmlCipher.doFinal(encodedDocument, encodedDocument.getDocumentElement());
         } else {
             NodeIterator iter =
-                    XPathAPI.selectNodeIterator(encodedDocument, secureTag);
+                XPathAPI.selectNodeIterator(encodedDocument, secureTag);
             Node node;
             while ((node = iter.nextNode()) != null) {
-                Document temp = xmlCipher.doFinal(encodedDocument, (Element) node, getSecureTagContents());
-                encodedDocument.importNode(temp.getDocumentElement().cloneNode(true), true);
+                if (getSecureTagContents()) {
+                    Document temp = xmlCipher.doFinal(encodedDocument, (Element) node, true);
+                    encodedDocument.importNode(temp.getDocumentElement().cloneNode(true), true);
+                } else {
+                    NodeList childNodes = node.getChildNodes();
+                    for (int i = 0; i < childNodes.getLength(); i++) {
+                        Node childNode = childNodes.item(i);
+                        if (childNode.getLocalName().equals("EncryptedData")) {
+                            Document temp = xmlCipher.doFinal(encodedDocument, (Element) childNode, false);
+                            encodedDocument.importNode(temp.getDocumentElement().cloneNode(true), true);
+                        }    
+                    }
+                }    
             }
         }
-
+        
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         try {
             DOMSource source = new DOMSource(encodedDocument);
@@ -167,8 +386,11 @@ public class XMLSecurityDataFormat imple
         // Return the decrypted data
         return bos.toByteArray();
     }
+    
+    
+    private Key generateKeyEncryptionKey(String algorithm) throws 
+            InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
 
-    private Key generateEncryptionKey(String algorithm) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
         DESedeKeySpec keySpec;
         Key secretKey;
         try {
@@ -188,11 +410,30 @@ public class XMLSecurityDataFormat imple
         }
         return secretKey;
     }
+    
+    private Key generateDataEncryptionKey() throws Exception {      
+        KeyGenerator keyGenerator = null;
+        if (xmlCipherAlgorithm.equalsIgnoreCase(XMLCipher.TRIPLEDES)) {
+            keyGenerator = KeyGenerator.getInstance("DESede");
+        } else {
+            keyGenerator = KeyGenerator.getInstance("AES");
+        }
+        if (xmlCipherAlgorithm.equalsIgnoreCase(XMLCipher.AES_128)) {
+            keyGenerator.init(128);
+        } else if (xmlCipherAlgorithm.equalsIgnoreCase(XMLCipher.AES_192)) {
+            keyGenerator.init(192);
+        } else if (xmlCipherAlgorithm.equalsIgnoreCase(XMLCipher.AES_256)) {
+            keyGenerator.init(256);
+        }
+        return keyGenerator.generateKey();
+    }
+
+    private void embedKeyInfoInEncryptedData(Document document, XMLCipher keyCipher, XMLCipher xmlCipher, Key dataEncryptionkey) 
+        throws XMLEncryptionException {
 
-    private void embedKeyInfoInEncryptedData(Document document, XMLCipher keyCipher, XMLCipher xmlCipher, Key dataEncryptionkey) throws XMLEncryptionException {
         EncryptedKey encryptedKey = keyCipher.encryptKey(document, dataEncryptionkey);
         KeyInfo keyInfo = new KeyInfo(document);
-        keyInfo.add(encryptedKey);
+        keyInfo.add(encryptedKey);    
         EncryptedData encryptedDataElement = xmlCipher.getEncryptedData();
         encryptedDataElement.setKeyInfo(keyInfo);
     }
@@ -211,6 +452,16 @@ public class XMLSecurityDataFormat imple
 
         return algorithmKeyWrap;
     }
+    
+    private String getRecipientKeyAlias(Exchange exchange) {
+        String alias = exchange.getIn().getHeader(XML_ENC_RECIPIENT_ALIAS, String.class);
+        if (alias != null) {
+            exchange.getIn().setHeader(XML_ENC_RECIPIENT_ALIAS, null);
+        } else {
+            alias = recipientKeyAlias;
+        }
+        return alias;
+    }
 
     public String getXmlCipherAlgorithm() {
         return xmlCipherAlgorithm;
@@ -219,6 +470,22 @@ public class XMLSecurityDataFormat imple
     public void setXmlCipherAlgorithm(String xmlCipherAlgorithm) {
         this.xmlCipherAlgorithm = xmlCipherAlgorithm;
     }
+    
+    public String getKeyCyperAlgorithm() {
+        return keyCipherAlgorithm;
+    }
+    
+    public void setKeyCipherAlgorithm(String keyCipherAlgorithm) {
+        this.keyCipherAlgorithm = keyCipherAlgorithm;
+    }
+    
+    public String getRecipientKeyAlias() {
+        return this.recipientKeyAlias;
+    }
+    
+    public void setRecipientKeyAlias(String recipientKeyAlias) {
+        this.recipientKeyAlias = recipientKeyAlias;
+    }
 
     public byte[] getPassPhrase() {
         return passPhrase;
@@ -247,5 +514,44 @@ public class XMLSecurityDataFormat imple
     public void setSecureTagContents(boolean secureTagContents) {
         this.secureTagContents = secureTagContents;
     }
-
+    
+    public KeyStore getKeyStore() {
+        return this.keyStore;
+    }
+    
+    public void setKeyStore(KeyStore keyStore) {
+        this.keyStore = keyStore;
+    }
+         
+    public KeyStore getTrustStore() {
+        return this.trustStore;
+    }
+    
+    public void setTrustStore(KeyStore trustStore) {
+        this.trustStore = trustStore;
+    }
+    
+    public String getKeyStoreAlias() {
+        return this.keyStoreAlias;
+    }
+    
+    public void setKeyStoreAlias(String keyStoreAlias) {
+        this.keyStoreAlias = keyStoreAlias;
+    }
+    
+    public String getKeyStorePassword() {
+        return this.keyStorePassword;
+    }
+    
+    public void setKeyStorePassword(String keyStorePassword) {
+        this.keyStorePassword = keyStorePassword;
+    }
+    
+    public String getTrustStorePassowrd() {
+        return this.trustStorePassword;
+    }
+    
+    public void setTrustStorePassword(String trustStorePassword) {
+        this.trustStorePassword = trustStorePassword;
+    }
 }

Modified: camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java?rev=1137849&r1=1137848&r2=1137849&view=diff
==============================================================================
--- camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java (original)
+++ camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormatTest.java Tue Jun 21 02:42:46 2011
@@ -18,6 +18,11 @@ package org.apache.camel.dataformat.xmls
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.net.URL;
+import java.security.KeyStore;
+import java.util.Map;
+
+import javax.xml.transform.OutputKeys;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
@@ -26,36 +31,43 @@ import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.converter.jaxp.XmlConverter;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.xml.security.encryption.XMLCipher;
+import org.junit.Ignore;
 import org.junit.Test;
 
-
 /**
  * Unit test of the encryptXML data format.
  */
 public class XMLSecurityDataFormatTest extends CamelTestSupport {
-    private static final String XML_FRAGMENT = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
-            + "<cheesesites>"
-            + "<netherlands>"
-            + "<source>cow</source>"
-            + "<cheese>gouda</cheese>"
-            + "</netherlands>"
-            + "<italy>"
-            + "<source>cow</source>"
-            + "<cheese>gorgonzola</cheese>"
-            + "</italy>"
-            + "<france>"
-            + "<source>goat</source>"
-            + "<cheese>brie</cheese>"
-            + "</france>"
-            + "</cheesesites>";
+    private static final String XML_FRAGMENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        + "<cheesesites>"
+        + "<netherlands>"
+        + "<source>cow</source>"
+        + "<cheese>gouda</cheese>"
+        + "</netherlands>"
+        + "<italy>"
+        + "<source>cow</source>"
+        + "<cheese>gorgonzola</cheese>"
+        + "</italy>"
+        + "<france>"
+        + "<source>goat</source>"
+        + "<cheese>brie</cheese>"
+        + "</france>"
+        + "</cheesesites>";
 
     @Override
     public boolean isUseRouteBuilder() {
         return false;
     }
+    
+    @Override 
+    public void setUp() throws Exception {
+        super.setUp();
+        context.getProperties().put(XmlConverter.OUTPUT_PROPERTIES_PREFIX + OutputKeys.ENCODING, "UTF-8");
+    }
 
     private void sendText() throws Exception {
         template.send("direct:start", new Processor() {
@@ -66,61 +78,117 @@ public class XMLSecurityDataFormatTest e
                 in.setBody(XML_FRAGMENT);
                 log.info("xmlFragment: " + XML_FRAGMENT);
             }
-
         });
     }
+    
+    private void testEncryption() throws Exception {
+        MockEndpoint resultEndpoint = context.getEndpoint("mock:encrypted", MockEndpoint.class);
+        resultEndpoint.setExpectedMessageCount(1);
+        context.start();
+        sendText();
+        resultEndpoint.assertIsSatisfied(100);
+        Exchange exchange = resultEndpoint.getExchanges().get(0);
+        Document inDoc = getDocumentForInMessage(exchange);
+        if (log.isDebugEnabled()) {
+            logMessage(exchange, inDoc);
+        }
+        assertTrue("The XML message has no encrypted data.", hasEncryptedData(inDoc));
+    }
+    
+    private void testDecryption() throws Exception {
+        MockEndpoint resultEndpoint = context.getEndpoint("mock:decrypted", MockEndpoint.class);
+        resultEndpoint.setExpectedMessageCount(1);
+        // verify that the message was encrypted before checking that it is decrypted
+        testEncryption();
+
+        resultEndpoint.assertIsSatisfied(100);
+        Exchange exchange = resultEndpoint.getExchanges().get(0);
+        Document inDoc = getDocumentForInMessage(exchange);
+        if (log.isDebugEnabled()) {
+            logMessage(exchange, inDoc);
+        }
+        assertFalse("The XML message has encrypted data.", hasEncryptedData(inDoc));
+        
+        // verify that the decrypted message matches what was sent
+        XmlConverter converter = new XmlConverter();
+        String xmlStr = converter.toString(inDoc, exchange);
+        assertTrue(xmlStr.equals(XML_FRAGMENT));
+    }
+    
+    private boolean hasEncryptedData(Document doc) throws Exception {
+        NodeList nodeList = doc.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData");
+        return nodeList.getLength() > 0;
+    }
+    
+    private void logMessage(Exchange exchange, Document inDoc) throws Exception {
+        XmlConverter converter = new XmlConverter();
+        String xmlStr = converter.toString(inDoc, exchange);
+        log.debug(xmlStr);   
+    }
+    
+    private Document getDocumentForInMessage(Exchange exchange) {
+        byte[] body = exchange.getIn().getBody(byte[].class);
+        Document d = createDocumentfromInputStream(new ByteArrayInputStream(body));
+        return d;
+    }
+    
+    private Document createDocumentfromInputStream(InputStream is) {
+        return context.getTypeConverter().convertTo(Document.class, is);
+    }
 
     /*
      * Encryption Tests
      */
+    
     @Test
     public void testFullPayloadXMLEncryption() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML().process(new EncryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML()
+                    .to("mock:encrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testEncryption();
     }
 
     @Test
-    public void testPartialPayloadXMLContentEncryption() throws Exception {
+    public void testPartialPayloadXMLContentEncryption() throws Exception {       
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/italy/cheese", true).process(new EncryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/italy/cheese", true)
+                    .to("mock:encrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testEncryption();
     }
 
     @Test
     public void testPartialPayloadMultiNodeXMLContentEncryption() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/*/cheese", true).process(new EncryptedXMLMessageProcessor());
+                from("direct:start")
+                     .marshal().secureXML("//cheesesites/*/cheese", true)
+                     .to("mock:encrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testEncryption();
     }
 
     @Test
     public void testPartialPayloadXMLElementEncryptionWithKey() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/france/cheese", false, "Just another 24 Byte key").process(new EncryptedXMLMessageProcessor());
-            }
+                from("direct:start")
+                     .marshal().secureXML("//cheesesites/france/cheese", false, "Just another 24 Byte key")
+                     .to("mock:encrypted");
+            }    
         });
-        context.start();
-
-        sendText();
+        testEncryption();
     }
 
+    @Ignore
     @Test
     public void testPartialPayloadXMLElementEncryptionWithKeyAndAlgorithm() throws Exception {
         final byte[] bits128 = {
@@ -132,14 +200,81 @@ public class XMLSecurityDataFormatTest e
         final String passCode = new String(bits128);
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/netherlands", false, passCode, XMLCipher.AES_128).process(new EncryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/netherlands", false, passCode, XMLCipher.AES_128)
+                    .to("mock:encrypted");
             }
         });
-        context.start();
+        testEncryption();
+    }
 
-        sendText();
+    @Ignore
+    @Test
+    public void testFullPayloadAsymmetricKeyEncryption() throws Exception {
+        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        URL trustStoreUrl = getClass().getClassLoader().getResource("sender.ts");
+        trustStore.load(trustStoreUrl.openStream(), "password".toCharArray());
+
+        final XMLSecurityDataFormat xmlEncDataFormat = new XMLSecurityDataFormat();
+        xmlEncDataFormat.setKeyCipherAlgorithm(XMLCipher.RSA_v1dot5);
+        xmlEncDataFormat.setXmlCipherAlgorithm(XMLCipher.AES_256);
+        xmlEncDataFormat.setTrustStore(trustStore);
+        xmlEncDataFormat.setTrustStorePassword("password");
+        xmlEncDataFormat.setRecipientKeyAlias("recipient");
+
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .marshal(xmlEncDataFormat).to("mock:encrypted");
+            }
+        });
+        testEncryption();
     }
 
+    @Ignore
+    @Test
+    public void testPartialPayloadAsymmetricKeyEncryptionWithContextTruststoreProperties() throws Exception {
+        Map<String, String> contextProps = context.getProperties();
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_URL, 
+            getClass().getClassLoader().getResource("sender.ts").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_PASSWORD, "password");
+ 
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/italy/cheese", true, "recipient", XMLCipher.AES_256, XMLCipher.RSA_v1dot5)
+                    .to("mock:encrypted");
+            }
+        });
+        testEncryption();
+    }
+ 
+    @Ignore
+    @Test
+    public void testPartialPayloadAsymmetricKeyEncryptionWithExchangeRecipientAlias() throws Exception {
+        MockEndpoint resultEndpoint = context.getEndpoint("mock:foo", MockEndpoint.class);
+        resultEndpoint.setExpectedMessageCount(1);
+ 
+        Map<String, String> contextProps = context.getProperties();
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_URL,
+            getClass().getClassLoader().getResource("sender.ts").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_PASSWORD, "password");
+ 
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .process(new Processor() {
+                        public void process(Exchange exchange) throws Exception {
+                            exchange.getIn().setHeader(XMLSecurityDataFormat.XML_ENC_RECIPIENT_ALIAS, "recipient");
+                        }
+                    })
+                    .marshal().secureXML("//cheesesites/italy/cheese", true, null, XMLCipher.AES_256, XMLCipher.RSA_v1dot5)
+                    .to("mock:encrypted");
+            }
+        });
+        testEncryption();
+    }
+ 
     /*
     * Decryption Tests
     */
@@ -147,53 +282,51 @@ public class XMLSecurityDataFormatTest e
     public void testFullPayloadXMLDecryption() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML().unmarshal().secureXML().process(new DecryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML().to("mock:encrypted")
+                    .unmarshal().secureXML().to("mock:decrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testDecryption();
     }
     
     @Test
     public void testPartialPayloadXMLContentDecryption() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/italy/cheese", true).
-                        unmarshal().secureXML("//cheesesites/italy/cheese", true).process(new DecryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/italy/cheese", true).to("mock:encrypted")
+                    .unmarshal().secureXML("//cheesesites/italy/cheese", true).to("mock:decrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testDecryption();
     }
     
     @Test
     public void testPartialPayloadMultiNodeXMLContentDecryption() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/*/cheese", true).
-                        unmarshal().secureXML("//cheesesites/*/cheese", true).process(new DecryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/*/cheese", true).to("mock:encrypted")
+                    .unmarshal().secureXML("//cheesesites/*/cheese", true).to("mock:decrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testDecryption();
     }
 
     @Test
     public void testPartialPayloadXMLElementDecryptionWithKey() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("//cheesesites/france/cheese", false, "Just another 24 Byte key").
-                        unmarshal().secureXML("//cheesesites/france", false, "Just another 24 Byte key").process(new DecryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/france/cheese", false, "Just another 24 Byte key").to("mock:encrypted")
+                    .unmarshal().secureXML("//cheesesites/france", false, "Just another 24 Byte key").to("mock:decrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testDecryption();
     }
 
+    @Ignore
     @Test
     public void testPartialPayloadXMLContentDecryptionWithKeyAndAlgorithm() throws Exception {
         final byte[] bits128 = {
@@ -204,58 +337,62 @@ public class XMLSecurityDataFormatTest e
         final String passCode = new String(bits128);
         context.addRoutes(new RouteBuilder() {
             public void configure() {
-                from("direct:start").marshal().secureXML("cheese", true, passCode, XMLCipher.AES_128).
-                        unmarshal().secureXML("cheese", true, passCode, XMLCipher.AES_128).process(new DecryptedXMLMessageProcessor());
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/italy", true, passCode, XMLCipher.AES_128).to("mock:encrypted")
+                    .unmarshal().secureXML("//cheesesites/italy", true, passCode, XMLCipher.AES_128).to("mock:decrypted");
             }
         });
-        context.start();
-
-        sendText();
+        testDecryption();
     }
 
+    @Ignore
+    @Test
+    public void testFullPayloadAsymmetricKeyDecryption() throws Exception {
 
-    private class EncryptedXMLMessageProcessor implements Processor {
-
-        public void process(Exchange exchange) throws Exception {
-            byte[] body = exchange.getIn().getBody(byte[].class);
-
-            Document d = createDocumentfromInputStream(new ByteArrayInputStream(body));
+        Map<String, String> contextProps = context.getProperties();
+        // context properties for encryption
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_URL, getClass().getClassLoader().getResource("sender.ts").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_PASSWORD, "password");
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_RECIPIENT_ALIAS, "recipient");
+
+        // context properties for decryption
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_URL, getClass().getClassLoader().getResource("recipient.ks").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_PASSWORD, "password");
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_ALIAS, "recipient");
 
-            // write to a string
-            XmlConverter converter = new XmlConverter();
-            String xmlStr = converter.toString(d, exchange);
-
-            NodeList nodeList = d.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData");
-            if (nodeList.getLength() >= 0) {
-                assertTrue(true);
-            } else {
-                assertTrue(false);
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .marshal().secureXML("", true, null, XMLCipher.AES_256, XMLCipher.RSA_v1dot5).to("mock:encrypted")
+                    .unmarshal().secureXML("", true, null, XMLCipher.AES_256, XMLCipher.RSA_v1dot5).to("mock:decrypted");
             }
-        }
+        });
+        testDecryption();
     }
 
-    private class DecryptedXMLMessageProcessor implements Processor {
+    @Ignore
+    @Test
+    public void testPartialPayloadAsymmetricKeyDecryption() throws Exception {
 
-        public void process(Exchange exchange) throws Exception {
-            byte[] body = exchange.getIn().getBody(byte[].class);
+        Map<String, String> contextProps = context.getProperties();
 
-            Document d = createDocumentfromInputStream(new ByteArrayInputStream(body));
+        // context properties for encryption
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_URL, getClass().getClassLoader().getResource("sender.ts").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_TRUST_STORE_PASSWORD, "password");
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_RECIPIENT_ALIAS, "recipient");
+
+        // context properties for decryption
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_URL, getClass().getClassLoader().getResource("recipient.ks").toString());
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_PASSWORD, "password");
+        contextProps.put(XMLSecurityDataFormat.XML_ENC_KEY_STORE_ALIAS, "recipient");
 
-            // write to a string
-            XmlConverter converter = new XmlConverter();
-            String xmlStr = converter.toString(d, exchange);
-
-            NodeList nodeList = d.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData");
-            if (nodeList.getLength() == 0) {
-                assertTrue(true);
-            } else {
-                assertTrue(false);
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .marshal().secureXML("//cheesesites/italy", true, null, XMLCipher.AES_256, XMLCipher.RSA_v1dot5).to("mock:encrypted")
+                    .unmarshal().secureXML("//cheesesites/italy", true, null, XMLCipher.AES_256, XMLCipher.RSA_v1dot5).to("mock:decrypted");
             }
-        }
-    }
-
-
-    private Document createDocumentfromInputStream(InputStream is) {
-        return context.getTypeConverter().convertTo(Document.class, is);
+        });
+        testDecryption();
     }
 }

Modified: camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/log4j.properties?rev=1137849&r1=1137848&r2=1137849&view=diff
==============================================================================
--- camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/log4j.properties (original)
+++ camel/branches/camel-2.7.x/components/camel-xmlsecurity/src/test/resources/log4j.properties Tue Jun 21 02:42:46 2011
@@ -20,10 +20,12 @@
 #
 log4j.rootLogger=INFO, file
 
+#log4j.logger.org.apache.camel.dataformat.xmlsecurity=DEBUG
+
 # CONSOLE appender not used by default
-log4j.appender.console=org.apache.log4j.ConsoleAppender
-log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%d %-5p %c{1} - %m %n
+log4j.appender.out=org.apache.log4j.ConsoleAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+log4j.appender.out.layout.ConversionPattern=%d %-5p %c{1} - %m %n
 
 # File appender
 log4j.appender.file=org.apache.log4j.FileAppender