You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by fo...@apache.org on 2017/07/25 08:20:04 UTC

[2/4] camel git commit: CAMEL-11438 new component crypto-cms

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierConfiguration.java b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierConfiguration.java
new file mode 100644
index 0000000..209c304
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierConfiguration.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.sig;
+
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.crypto.cms.common.CryptoCmsConstants;
+import org.apache.camel.component.crypto.cms.common.CryptoCmsUnMarshallerConfiguration;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsException;
+
+public interface SignedDataVerifierConfiguration extends CryptoCmsUnMarshallerConfiguration {
+
+    /**
+     * Indicates whether the value in the Signed Data header (given by
+     * {@link CryptoCmsConstants#CAMEL_CRYPTO_CMS_SIGNED_DATA} is base64
+     * encoded.
+     */
+    Boolean isSignedDataHeaderBase64(Exchange exchange) throws CryptoCmsException;
+
+    /**
+     * If <code>true</code> then the signatures of all signers are checked. If
+     * <code>false</code> then the verifier searches for a signer which matches
+     * with one of the specified certificates and verifies only the signature of
+     * the first found signer.
+     */
+    Boolean isVerifySignaturesOfAllSigners(Exchange exchange) throws CryptoCmsException;
+
+    /**
+     * Returns the collection of certificates whose public keys are used to
+     * verify the signatures contained in the Signed Data object if the
+     * certificates match the signer information given in the Signed Data
+     * object.
+     */
+    Collection<X509Certificate> getCertificates(Exchange exchange) throws CryptoCmsException;
+
+    /** Creates a copy of this instance. For example by cloning. */
+    SignedDataVerifierConfiguration copy();
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierFromHeader.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierFromHeader.java b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierFromHeader.java
new file mode 100644
index 0000000..8ddbf30
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignedDataVerifierFromHeader.java
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.sig;
+
+import java.io.InputStream;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.crypto.cms.common.CryptoCmsConstants;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsFormatException;
+import org.apache.camel.util.IOHelper;
+import org.apache.commons.codec.binary.Base64InputStream;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.CMSSignedDataParser;
+import org.bouncycastle.cms.CMSTypedStream;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Verifies the signature contained in the header
+ * {@link CryptoCmsConstants#CAMEL_CRYPTO_CMS_SIGNED_DATA}.
+ */
+public class SignedDataVerifierFromHeader extends SignedDataVerifier {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SignedDataVerifierFromHeader.class);
+
+    private SignedDataVerifierConfiguration conf;
+
+    public SignedDataVerifierFromHeader(SignedDataVerifierConfiguration conf) {
+        super(conf);
+        this.conf = conf;
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception { // NOPMD see
+                                                              // method
+                                                              // processSignedDataHader
+
+        InputStream signature = exchange.getIn().getHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA, InputStream.class);
+        if (signature == null) {
+            LOG.debug("No signed data found in header {}. Assuming signed data contained in message body", CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA);
+            super.process(exchange);
+        } else {
+            LOG.debug("Signed data header {} found.", CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA);
+            processSignedDataHeader(exchange, signature);
+
+            // remove header
+            exchange.getIn().removeHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA);
+        }
+    }
+
+    protected void processSignedDataHeader(Exchange exchange, InputStream signature) throws Exception { // NOPMD
+        // all exceptions must be caught and re-thrown in order to make a
+        // clean-up, see code below
+        if (conf.isSignedDataHeaderBase64(exchange)) {
+            signature = new Base64InputStream(signature);
+        }
+
+        InputStream stream = exchange.getIn().getMandatoryBody(InputStream.class);
+        try {
+            // lets setup the out message before we invoke the dataFormat
+            // so that it can mutate it if necessary
+            Message out = exchange.getOut();
+            out.copyFrom(exchange.getIn());
+
+            if (conf.isFromBase64(exchange)) {
+                stream = new Base64InputStream(stream);
+            }
+            unmarshalInternal(stream, signature, exchange);
+        } catch (Exception e) {
+            // remove OUT message, as an exception occurred
+            exchange.setOut(null);
+            throw e;
+        } finally {
+            IOHelper.close(stream, "input stream");
+        }
+    }
+
+    protected void unmarshalInternal(InputStream is, InputStream signature, Exchange exchange) throws Exception {
+
+        CMSSignedDataParser sp;
+        try {
+            sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build(), new CMSTypedStream(is), signature);
+        } catch (CMSException e) {
+            throw new CryptoCmsFormatException(getFormatErrorMessage(), e);
+        }
+        try {
+            // content must be read in order to calculate the hash for the
+            // signature
+            sp.getSignedContent().drain();
+        } catch (NullPointerException e) { // nullpointer exception is thrown
+                                           // when the signed content is missing
+            throw getContentMissingException(e);
+        }
+
+        LOG.debug("Signed data found");
+        debugLog(sp);
+        verify(sp, exchange);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignerInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignerInfo.java b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignerInfo.java
new file mode 100644
index 0000000..b7da85a
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/java/org/apache/camel/component/crypto/cms/sig/SignerInfo.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.sig;
+
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsException;
+import org.bouncycastle.cms.CMSAttributeTableGenerator;
+
+/**
+ * Signer information.
+ */
+public interface SignerInfo {
+
+    String getSignatureAlgorithm(Exchange exchange) throws CryptoCmsException;
+
+    PrivateKey getPrivateKey(Exchange exchange) throws CryptoCmsException;
+
+    X509Certificate getCertificate(Exchange exchange) throws CryptoCmsException;
+
+    /**
+     * Certificates which should be added to the certificate list of the Signed
+     * Data instance which belong to the private key. Return an empty array if
+     * you do not want that the certificate chain of the private key to be added
+     * to the signature certificates.
+     */
+    Certificate[] getCertificateChain(Exchange exchange) throws CryptoCmsException;
+
+    /**
+     * Returns the generator for the signed attributes.
+     */
+    CMSAttributeTableGenerator getSignedAttributeGenerator(Exchange exchange) throws CryptoCmsException;
+
+    /**
+     * Returns the generator for the unsigned attributes. Can be
+     * <code>null</code>, then no unsigned attribute is generated.
+     */
+    CMSAttributeTableGenerator getUnsignedAttributeGenerator(Exchange exchange) throws CryptoCmsException;
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/resources/META-INF/LICENSE.txt b/components/camel-crypto-cms/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/resources/META-INF/NOTICE.txt b/components/camel-crypto-cms/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/main/resources/META-INF/services/org/apache/camel/component/crypto-cms
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/main/resources/META-INF/services/org/apache/camel/component/crypto-cms b/components/camel-crypto-cms/src/main/resources/META-INF/services/org/apache/camel/component/crypto-cms
new file mode 100644
index 0000000..542d209
--- /dev/null
+++ b/components/camel-crypto-cms/src/main/resources/META-INF/services/org/apache/camel/component/crypto-cms
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.component.crypto.cms.CryptoCmsComponent

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ComponentTest.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ComponentTest.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ComponentTest.java
new file mode 100644
index 0000000..497aa70
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ComponentTest.java
@@ -0,0 +1,170 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms;
+
+import java.io.InputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.crypto.cms.crypt.DefaultKeyTransRecipientInfo;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsVerifierCertificateNotValidException;
+import org.apache.camel.component.crypto.cms.sig.DefaultSignerInfo;
+import org.apache.camel.component.crypto.cms.util.KeystoreUtil;
+import org.apache.camel.component.crypto.cms.util.TestAttributesGeneratorProvider;
+import org.apache.camel.component.crypto.cms.util.TestOriginatorInformationProvider;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.SimpleRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.jsse.KeyStoreParameters;
+import org.junit.Test;
+
+public class ComponentTest extends CamelTestSupport {
+
+    private SimpleRegistry simpleReg;
+
+    @Test
+    public void execute() throws Exception {
+
+        String message = "Testmessage";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived(message);
+        sendBody("direct:start", message.getBytes("UTF-8"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void signedWithOutdatedCert() throws Exception {
+
+        String message = "Testmessage";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(0);
+        MockEndpoint mockException = getMockEndpoint("mock:exception");
+        mockException.expectedMessageCount(1);
+
+        sendBody("direct:outdated", message.getBytes("UTF-8"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void decryptAndVerify() throws Exception {
+
+        InputStream input = this.getClass().getClassLoader().getResourceAsStream("signed_enveloped_other_CMS_vendor.binary");
+        assertNotNull(input);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Testmessage");
+        sendBody("direct:decryptAndVerify", input);
+
+        assertMockEndpointsSatisfied();
+
+        input.close();
+
+    }
+
+    @Test
+    public void orignatorUnprotectedAttributes() throws Exception {
+
+        String message = "Testmessage";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived(message);
+        sendBody("direct:encryptDecryptOriginatorAttributes", message.getBytes("UTF-8"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    protected CamelContext createCamelContext() throws Exception {
+        simpleReg = new SimpleRegistry();
+        CamelContext context = new DefaultCamelContext(simpleReg);
+        return context;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                context.setTracing(true);
+                context.setStreamCaching(true);
+
+                KeyStoreParameters keystore = KeystoreUtil.getKeyStoreParameters("system.jks");
+
+                DefaultKeyTransRecipientInfo recipient = new DefaultKeyTransRecipientInfo();
+                recipient.setCertificateAlias("rsa");
+                recipient.setKeyStoreParameters(keystore);
+
+                DefaultSignerInfo signerInfo = new DefaultSignerInfo();
+                signerInfo.setIncludeCertificates(true); // optional default
+                                                         // value is true
+                signerInfo.setSignatureAlgorithm("SHA256withRSA"); // mandatory
+                signerInfo.setPrivateKeyAlias("rsa");
+                signerInfo.setKeyStoreParameters(keystore);
+
+                DefaultSignerInfo signerInfo2 = new DefaultSignerInfo();
+                signerInfo2.setSignatureAlgorithm("SHA256withDSA"); // mandatory
+                signerInfo2.setPrivateKeyAlias("dsa");
+                signerInfo2.setKeyStoreParameters(keystore);
+
+                getContext().addComponent("crypto-cms", new CryptoCmsComponent(getContext()));
+
+                simpleReg.put("keyStoreParameters", keystore);
+                simpleReg.put("signer1", signerInfo);
+                simpleReg.put("signer2", signerInfo2);
+                simpleReg.put("recipient1", recipient);
+
+                onException(CryptoCmsVerifierCertificateNotValidException.class).handled(false).to("mock:exception");
+
+                from("direct:start").to("crypto-cms:sign://testsign?signer=#signer1&signer=#signer2&includeContent=true")
+                    .to("crypto-cms:encrypt://testencrpyt?toBase64=true&recipient=#recipient1&contentEncryptionAlgorithm=DESede/CBC/PKCS5Padding&secretKeyLength=128")
+                    // .to("file:target/test_signed_encrypted.base64")
+                    .to("crypto-cms:decrypt://testdecrypt?fromBase64=true&keyStoreParameters=#keyStoreParameters")
+                    .to("crypto-cms:verify://testverify?keyStoreParameters=#keyStoreParameters").convertBodyTo(String.class).to("log:after").to("mock:result");
+
+                DefaultSignerInfo signerOutdated = new DefaultSignerInfo();
+                signerOutdated.setIncludeCertificates(false);
+                signerOutdated.setSignatureAlgorithm("SHA1withRSA");
+                signerOutdated.setPrivateKeyAlias("outdated");
+                signerOutdated.setKeyStoreParameters(keystore);
+                simpleReg.put("signerOutdated", signerOutdated);
+
+                from("direct:outdated").to("crypto-cms:sign://outdated?signer=#signerOutdated&includeContent=true")
+                    .to("crypto-cms:verify://outdated?keyStoreParameters=#keyStoreParameters").to("mock:result");
+
+                from("direct:decryptAndVerify").to("crypto-cms:decrypt://testdecrypt?fromBase64=true&keyStoreParameters=#keyStoreParameters")
+                    .to("crypto-cms:verify://testverify?keyStoreParameters=#keyStoreParameters").to("mock:result");
+
+                TestOriginatorInformationProvider originatorInformationProvider = new TestOriginatorInformationProvider();
+                TestAttributesGeneratorProvider attributesGeneratorProvider = new TestAttributesGeneratorProvider();
+                simpleReg.put("originatorInformationProvider1", originatorInformationProvider);
+                simpleReg.put("attributesGeneratorProvider1", attributesGeneratorProvider);
+
+                from("direct:encryptDecryptOriginatorAttributes")
+                    .to("crypto-cms:encrypt://testencrpyt?toBase64=true&recipient=#recipient1&contentEncryptionAlgorithm=DESede/CBC/PKCS5Padding&secretKeyLength=128&"
+                        + "originatorInformationProvider=#originatorInformationProvider1&unprotectedAttributesGeneratorProvider=#attributesGeneratorProvider1")
+                    .to("crypto-cms:decrypt://testdecrypt?fromBase64=true&keyStoreParameters=#keyStoreParameters").to("mock:result");
+            }
+        };
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void wrongOperation() throws Exception {
+        CryptoCmsComponent c = new CryptoCmsComponent(new DefaultCamelContext());
+        c.createEndpoint("uri", "wrongoperation", null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/EnvelopedDataTest.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/EnvelopedDataTest.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/EnvelopedDataTest.java
new file mode 100644
index 0000000..49579bd
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/EnvelopedDataTest.java
@@ -0,0 +1,430 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.crypto.cms.crypt.DefaultEnvelopedDataDecryptorConfiguration;
+import org.apache.camel.component.crypto.cms.crypt.DefaultKeyTransRecipientInfo;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataDecryptor;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataEncryptor;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataEncryptorConfiguration;
+import org.apache.camel.component.crypto.cms.crypt.RecipientInfo;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsFormatException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsNoCertificateForRecipientsException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsNoKeyOrCertificateForAliasException;
+import org.apache.camel.component.crypto.cms.util.ExchangeUtil;
+import org.apache.camel.component.crypto.cms.util.KeystoreUtil;
+import org.apache.camel.util.jsse.KeyStoreParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class EnvelopedDataTest {
+
+    @BeforeClass
+    public static void setUpProvider() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Test
+    public void executeDESedeCBClength192() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "DESede/CBC/PKCS5Padding", 192);
+    }
+
+    @Test
+    public void executeDESedeCBClength128() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "DESede/CBC/PKCS5Padding", 128);
+    }
+
+    @Test
+    public void executeDESCBCkeyLength64() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "DES/CBC/PKCS5Padding", 64);
+    }
+
+    @Test
+    public void executeDESCBCkeyLength56() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "DES/CBC/PKCS5Padding", 56);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength128() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 128);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength120() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 120);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength112() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 112);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength104() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 104);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength96() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 96);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength88() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 88);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength80() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 80);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength72() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 72);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength64() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 64);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength56() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 56);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength48() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 48);
+    }
+
+    @Test
+    public void executeCAST5CBCkeyLength40() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "CAST5/CBC/PKCS5Padding", 40);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength128() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 128);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength120() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 120);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength112() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 112);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength104() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 104);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength96() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 96);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength88() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 88);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength80() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 80);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength72() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 72);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength64() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 64);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength56() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 56);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength48() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 48);
+    }
+
+    @Test
+    public void executeRC2CBCkeyLength40() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC2/CBC/PKCS5Padding", 40);
+    }
+
+    @Test
+    public void executeCamelliaCBCKeySize128() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "Camellia/CBC/PKCS5Padding", 128);
+    }
+
+    /** Works if strong encryption policy jars are installed. */
+    @Ignore
+    @Test(expected = CryptoCmsException.class)
+    public void executeCamelliaCBCKeySize256() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "Camellia/CBC/PKCS5Padding", 256);
+    }
+
+    /** Works if strong encryption policy jars are installed. */
+    @Ignore
+    @Test(expected = CryptoCmsException.class)
+    public void executeCamelliaCBCKeySize192() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "Camellia/CBC/PKCS5Padding", 192);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNoInWhiteListCamellia256CBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "Camellia256/CBC/PKCS5Padding", 256);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListCamellia192CBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "Camellia192/CBC/PKCS5Padding", 192);
+    }
+
+    /** Works if strong encryption policy jars are installed. */
+    @Ignore
+    @Test(expected = CryptoCmsException.class)
+    public void executeAESCBCKeySize256() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES/CBC/PKCS5Padding", 256);
+    }
+
+    /** Works if strong encryption policy jars are installed. */
+    @Ignore
+    @Test(expected = CryptoCmsException.class)
+    public void executeAESCBCKeySize192() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES/CBC/PKCS5Padding", 192);
+    }
+
+    @Test
+    public void executeAESCBCKeySize128() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES/CBC/PKCS5Padding", 128);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES256CBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES256/CBC/PKCS5Padding", 256);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES192CBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES192/CBC/PKCS5Padding", 192);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executerNoImplRSAECB() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RSA/ECB/OAEP", 0);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAESGCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES/GCM/NoPadding", 128);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES192GCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES192/GCM/NoPadding", 192);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES256GCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES256/GCM/NoPadding", 256);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES256CCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES256/CCM/NoPadding", 256);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListIDEACBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "IDEA/CBC/PKCS5Padding", 128);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAESCCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES/CCM/NoPadding", 128);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListAES192CCM() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "AES192/CCM/NoPadding", 192);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void executeNotInWhiteListRC5CBC() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "RC5/CBC/PKCS5Padding", 0);
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void wrongSecretKeyLength() throws Exception {
+        encrypt("system.jks", "DESede/CBC/PKCS5Padding", 200, "testMessage", "rsa");
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void wrongContentEncryptionAlgorithm() throws Exception {
+        encryptDecrypt("system.jks", "rsa", "WrongDESede/CBC/PKCS5Padding", 200);
+    }
+
+    @Test(expected = CryptoCmsNoKeyOrCertificateForAliasException.class)
+    public void wrongEncryptAlias() throws Exception {
+        encrypt("system.jks", "DESede/CBC/PKCS5Padding", 128, "testMessage", "wrongAlias");
+    }
+
+    @Test(expected = CryptoCmsNoKeyOrCertificateForAliasException.class)
+    public void encryptWrongAliasAndCorrectAlias() throws Exception {
+        encrypt("system.jks", "DESede/CBC/PKCS5Padding", 128, "testMessage", "wrongAlias", "rsa");
+    }
+
+    @Test(expected = CryptoCmsNoKeyOrCertificateForAliasException.class)
+    public void encryptTwoWrongAliases() throws Exception {
+        encrypt("system.jks", "DESede/CBC/PKCS5Padding", 128, "testMessage", "wrongAlias", "wrongAlias2");
+    }
+
+    @Test
+    public void encryptTwoCorrectAliases() throws Exception {
+        encrypt("system.jks", "DESede/CBC/PKCS5Padding", 128, "testMessage", "rsa2", "rsa");
+    }
+
+    @Test(expected = CryptoCmsFormatException.class)
+    public void wrongEncryptedMessage() throws Exception {
+        decrypt("system.jks", "TestMessage".getBytes());
+    }
+
+    @Test(expected = CryptoCmsFormatException.class)
+    public void wrongEncryptedEmptyMessage() throws Exception {
+        decrypt("system.jks", new byte[0]);
+    }
+
+    @Test
+    public void decryptionWithEmptyAlias() throws Exception {
+
+        byte[] bytes = null;
+        try {
+            bytes = encrypt("system.jks", "DESede/CBC/PKCS5Padding", 192, "Test Message", "rsa");
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception: " + e.getMessage());
+        }
+        decrypt("system.jks", bytes);
+    }
+
+    @Test(expected = CryptoCmsNoCertificateForRecipientsException.class)
+    public void decryptionWithNullAliasWrongKeystore() throws Exception {
+
+        byte[] bytes = null;
+        try {
+            bytes = encrypt("system.jks", "DESede/CBC/PKCS5Padding", 192, "Test Message", "rsa");
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception: " + e.getMessage());
+        }
+        decrypt("test.jks", bytes);
+    }
+
+    // @Test
+    // public void invalidContentTypeEnvelopedData() throws Exception {
+    // try {
+    // encryptDecrypt("system.jks", "rsa", "DESede/CBC/PKCS5Padding", 192,
+    // CmsEnvelopedDataDecryptorConfiguration.SIGNEDANDENVELOPEDDATA);
+    // } catch (CmsException e) {
+    // Assert.assertTrue(e.getMessage().contains("The PKCS#7/CMS decryptor step
+    // does not accept PKCS#7/CMS messages of content type 'Enveloped Data'"));
+    // return;
+    // }
+    // Assert.fail("Exception expected");
+    // }
+
+    private void encryptDecrypt(String keystoreName, String alias, String contentEncryptionAlgorithm, int secretKeyLength) throws Exception {
+        String message = "Test Message";
+
+        byte[] encrypted = encrypt(keystoreName, contentEncryptionAlgorithm, secretKeyLength, message, alias);
+        byte[] decrypted = decrypt(keystoreName, encrypted);
+
+        String actual = new String(decrypted, "UTF-8");
+        Assert.assertEquals(message, actual);
+    }
+
+    private byte[] encrypt(String keystoreName, String contentEncryptionAlgorithm, int secretKeyLength, String message, String... aliases)
+        throws UnsupportedEncodingException, Exception {
+        KeyStoreParameters keystorePas = KeystoreUtil.getKeyStoreParameters(keystoreName);
+
+        List<RecipientInfo> recipients = new ArrayList<RecipientInfo>(aliases.length);
+        for (String alias : aliases) {
+            DefaultKeyTransRecipientInfo recipient = new DefaultKeyTransRecipientInfo();
+            recipient.setCertificateAlias(alias);
+            recipient.setKeyStoreParameters(keystorePas);
+            recipients.add(recipient);
+        }
+
+        EnvelopedDataEncryptorConfiguration enConf = new EnvelopedDataEncryptorConfiguration(null);
+        enConf.setContentEncryptionAlgorithm(contentEncryptionAlgorithm);
+        for (RecipientInfo recipient : recipients) {
+            enConf.setRecipient(recipient);
+        }
+        enConf.setSecretKeyLength(secretKeyLength); // optional
+        // enConf.setBlockSize(2048); // optional
+        enConf.init();
+        EnvelopedDataEncryptor encryptor = new EnvelopedDataEncryptor(enConf);
+
+        Exchange exchange = ExchangeUtil.getExchange();
+        exchange.getIn().setBody(new ByteArrayInputStream(message.getBytes("UTF-8")));
+        encryptor.process(exchange);
+        byte[] encrypted = (byte[])exchange.getOut().getBody();
+        return encrypted;
+    }
+
+    private byte[] decrypt(String keystoreName, byte[] encrypted) throws UnsupportedEncodingException, Exception, IOException {
+
+        KeyStoreParameters keystore = KeystoreUtil.getKeyStoreParameters(keystoreName);
+
+        Exchange exchangeDecrypt = ExchangeUtil.getExchange();
+        exchangeDecrypt.getIn().setBody(new ByteArrayInputStream(encrypted));
+
+        DefaultEnvelopedDataDecryptorConfiguration conf = new DefaultEnvelopedDataDecryptorConfiguration();
+        conf.setKeyStoreParameters(keystore);
+        EnvelopedDataDecryptor decryptor = new EnvelopedDataDecryptor(conf);
+
+        decryptor.process(exchangeDecrypt);
+
+        byte[] decrypted = (byte[])exchangeDecrypt.getOut().getBody();
+
+        return decrypted;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ProcessorsTest.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ProcessorsTest.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ProcessorsTest.java
new file mode 100644
index 0000000..4aefdfa
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/ProcessorsTest.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms;
+
+import java.security.Security;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.crypto.cms.crypt.DefaultEnvelopedDataDecryptorConfiguration;
+import org.apache.camel.component.crypto.cms.crypt.DefaultKeyTransRecipientInfo;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataDecryptor;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataEncryptor;
+import org.apache.camel.component.crypto.cms.crypt.EnvelopedDataEncryptorConfiguration;
+import org.apache.camel.component.crypto.cms.sig.DefaultSignedDataVerifierConfiguration;
+import org.apache.camel.component.crypto.cms.sig.DefaultSignerInfo;
+import org.apache.camel.component.crypto.cms.sig.SignedDataCreator;
+import org.apache.camel.component.crypto.cms.sig.SignedDataCreatorConfiguration;
+import org.apache.camel.component.crypto.cms.sig.SignedDataVerifier;
+import org.apache.camel.component.crypto.cms.util.KeystoreUtil;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.SimpleRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.jsse.KeyStoreParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ProcessorsTest extends CamelTestSupport {
+
+    private SimpleRegistry simpleReg;
+
+    @BeforeClass
+    public static void setUpProvider() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Test
+    public void execute() throws Exception {
+
+        String message = "Testmessage";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived(message);
+        sendBody("direct:start", message);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    protected CamelContext createCamelContext() throws Exception {
+        simpleReg = new SimpleRegistry();
+        CamelContext context = new DefaultCamelContext(simpleReg);
+        return context;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                context.setTracing(true);
+
+                String keystoreName = "system.jks";
+                KeyStoreParameters keystore = KeystoreUtil.getKeyStoreParameters(keystoreName);
+
+                DefaultKeyTransRecipientInfo recipient = new DefaultKeyTransRecipientInfo();
+                recipient.setCertificateAlias("rsa");
+                recipient.setKeyStoreParameters(keystore);
+
+                EnvelopedDataEncryptorConfiguration enConf = new EnvelopedDataEncryptorConfiguration(context);
+                enConf.setContentEncryptionAlgorithm("DESede/CBC/PKCS5Padding");
+                enConf.setRecipient(recipient);
+                enConf.setSecretKeyLength(192); // mandatory
+                enConf.init();
+                EnvelopedDataEncryptor encryptor = new EnvelopedDataEncryptor(enConf);
+
+                DefaultEnvelopedDataDecryptorConfiguration conf = new DefaultEnvelopedDataDecryptorConfiguration();
+                conf.setKeyStoreParameters(keystore);
+                EnvelopedDataDecryptor decryptor = new EnvelopedDataDecryptor(conf);
+
+                DefaultSignerInfo signerInfo = new DefaultSignerInfo();
+
+                signerInfo.setIncludeCertificates(true); // optional default
+                                                         // value is true
+                signerInfo.setSignatureAlgorithm("SHA256withRSA"); // mandatory
+                signerInfo.setPrivateKeyAlias("rsa");
+                signerInfo.setKeyStoreParameters(keystore);
+
+                SignedDataCreatorConfiguration config = new SignedDataCreatorConfiguration(new DefaultCamelContext());
+                config.setSigner(signerInfo);
+                config.setIncludeContent(true); // optional default value is
+                                                // true
+                config.init();
+                SignedDataCreator signer = new SignedDataCreator(config);
+
+                DefaultSignedDataVerifierConfiguration verifierConf = new DefaultSignedDataVerifierConfiguration();
+                verifierConf.setKeyStoreParameters(keystore);
+
+                SignedDataVerifier verifier = new SignedDataVerifier(verifierConf);
+
+                from("direct:start").to("log:before").process(signer).process(encryptor).to("log:signed_encrypted").process(decryptor).process(verifier).convertBodyTo(String.class)
+                    .to("log:after").to("mock:result");
+
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/SignedDataTest.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/SignedDataTest.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/SignedDataTest.java
new file mode 100644
index 0000000..9d4b448
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/SignedDataTest.java
@@ -0,0 +1,483 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.crypto.cms.common.CryptoCmsConstants;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsFormatException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsInvalidKeyException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsNoCertificateForSignerInfoException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsNoCertificateForSignerInfosException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsNoKeyOrCertificateForAliasException;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsSignatureInvalidContentHashException;
+import org.apache.camel.component.crypto.cms.sig.DefaultSignedDataVerifierConfiguration;
+import org.apache.camel.component.crypto.cms.sig.DefaultSignerInfo;
+import org.apache.camel.component.crypto.cms.sig.SignedDataCreator;
+import org.apache.camel.component.crypto.cms.sig.SignedDataCreatorConfiguration;
+import org.apache.camel.component.crypto.cms.sig.SignedDataVerifier;
+import org.apache.camel.component.crypto.cms.sig.SignedDataVerifierFromHeader;
+import org.apache.camel.component.crypto.cms.sig.SignerInfo;
+import org.apache.camel.component.crypto.cms.util.ExchangeUtil;
+import org.apache.camel.component.crypto.cms.util.KeystoreUtil;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.jsse.KeyStoreParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class SignedDataTest {
+
+    @BeforeClass
+    public static void setUpProvider() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Test
+    public void testWithCertificatesIncluded() throws Exception {
+        signAndVerify("Test Message", "system.jks", "SHA1withRSA", "rsa", true, true);
+    }
+
+    @Test
+    public void testWithCertificatesIncludedNoSignedAttributes() throws Exception {
+        signAndVerify("Test Message", "system.jks", "SHA1withRSA", "rsa", true, true);
+    }
+
+    @Test
+    public void testWithCertificatesIncludedTimestampSignedAttribute() throws Exception {
+        signAndVerify("Test Message", "system.jks", "SHA1withRSA", "rsa", true, true);
+    }
+
+    @Test
+    public void testWithCertificatesIncludedCertificateSignedAttribute() throws Exception {
+        signAndVerify("Test Message", "system.jks", "SHA1withRSA", "rsa", true, true);
+    }
+
+    @Test
+    public void testWithoutCertificatesIncludedAndDigestAlgorithmSHA1andSignatureAlgorithm() throws Exception {
+        signAndVerify("Test Message", "system.jks", "SHA1withDSA", "dsa", true, false);
+    }
+
+    private void signAndVerify(String message, String keystoreName, String signatureAlgorithm, String alias, boolean includeContent, boolean includeCertificates)
+        throws UnsupportedEncodingException, Exception {
+
+        byte[] signed = sign(message, keystoreName, signatureAlgorithm, includeContent, includeCertificates, alias);
+        byte[] result = verify(keystoreName, alias, signed, false);
+
+        Assert.assertEquals(message, new String(result, "UTF-8"));
+    }
+
+    private byte[] sign(String message, String keystoreName, String signatureAlgorithm, boolean includeContent, boolean includeCertificates, String... aliases)
+        throws UnsupportedEncodingException, Exception {
+        KeyStoreParameters keystore = KeystoreUtil.getKeyStoreParameters(keystoreName);
+
+        List<SignerInfo> signers = new ArrayList<SignerInfo>(aliases.length);
+        for (String alias : aliases) {
+            DefaultSignerInfo signerInfo = new DefaultSignerInfo();
+            signerInfo.setIncludeCertificates(includeCertificates); // without
+                                                                    // certificates,
+                                                                    // optional
+                                                                    // default
+                                                                    // value is
+                                                                    // true
+            signerInfo.setSignatureAlgorithm(signatureAlgorithm); // mandatory
+            signerInfo.setPrivateKeyAlias(alias);
+            signerInfo.setKeyStoreParameters(keystore);
+            signers.add(signerInfo);
+        }
+
+        SignedDataCreatorConfiguration config = new SignedDataCreatorConfiguration(new DefaultCamelContext());
+        for (SignerInfo signer : signers) {
+            config.setSigner(signer);
+        }
+        // config.setBlockSize(blockSize); // optional
+        config.setIncludeContent(includeContent); // optional default value is
+                                                  // true
+        config.init();
+        SignedDataCreator signer = new SignedDataCreator(config);
+
+        Exchange exchange = ExchangeUtil.getExchange();
+        exchange.getIn().setBody(new ByteArrayInputStream(message.getBytes("UTF-8")));
+        signer.process(exchange);
+        byte[] signed = (byte[])exchange.getOut().getBody();
+        return signed;
+    }
+
+    private byte[] verify(String keystoreName, String alias, byte[] signed, boolean base64) throws Exception, UnsupportedEncodingException {
+        DefaultSignedDataVerifierConfiguration verifierConf = getCryptoCmsSignedDataVerifierConf(keystoreName, Collections.singletonList(alias), base64);
+
+        SignedDataVerifier verifier = new SignedDataVerifier(verifierConf);
+
+        InputStream is = new BufferedInputStream(new ByteArrayInputStream(signed));
+        Exchange exchangeVeri = ExchangeUtil.getExchange();
+        exchangeVeri.getIn().setBody(is);
+        verifier.process(exchangeVeri);
+        byte[] result = (byte[])exchangeVeri.getOut().getBody();
+        return result;
+    }
+
+    DefaultSignedDataVerifierConfiguration getCryptoCmsSignedDataVerifierConf(String keystoreName, Collection<String> aliases, boolean base64)
+        throws GeneralSecurityException, IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
+        KeyStoreParameters keystorePas = KeystoreUtil.getKeyStoreParameters(keystoreName);
+        KeyStore keystore = keystorePas.createKeyStore();
+
+        KeyStore verifierKeystore = KeyStore.getInstance("JCEKS");
+        verifierKeystore.load(null, "".toCharArray());
+        // add only verifier certs
+        for (String alias : aliases) {
+            Certificate verifierCert = keystore.getCertificate(alias);
+            if (verifierCert != null) {
+                verifierKeystore.setCertificateEntry(alias, verifierCert);
+            }
+        }
+        DefaultSignedDataVerifierConfiguration verifierConf = new DefaultSignedDataVerifierConfiguration();
+
+        verifierConf.setKeyStore(verifierKeystore);
+        verifierConf.setFromBase64(base64);
+        return verifierConf;
+    }
+
+    @Test
+    public void signWithTwoAliases() throws Exception {
+        sign("", "system.jks", "SHA1withRSA", true, false, "rsa", "rsa2");
+    }
+
+    @Test(expected = CryptoCmsNoKeyOrCertificateForAliasException.class)
+    public void signWithTwoAliasesOneWithNoPrivateKeyInKeystore() throws Exception {
+        sign("Test Message", "system.jks", "SHA1withDSA", true, false, "dsa", "noEntry");
+    }
+
+    @Test(expected = CryptoCmsNoKeyOrCertificateForAliasException.class)
+    public void signWrongAlias() throws Exception {
+        sign("Test Message", "system.jks", "SHA1withDSA", true, false, "wrong");
+
+    }
+
+    @Test
+    public void signEmptyContent() throws Exception {
+        sign("", "system.jks", "SHA1withDSA", true, false, "dsa");
+    }
+
+    @Test(expected = CryptoCmsInvalidKeyException.class)
+    public void signSignatureAlgorithmNotCorrespondingToPrivateKey() throws Exception {
+        sign("testMessage", "system.jks", "MD5withRSA", true, false, "dsa");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void signWrongSignatureAlgorithm() throws Exception {
+        sign("testMessage", "system.jks", "wrongRSA", true, false, "rsa");
+    }
+
+    @Test
+    public void verifySignedDataWithoutSignedContent() throws Exception {
+        InputStream is = SignedDataTest.class.getClassLoader().getResourceAsStream("detached_signature.binary");
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        IOHelper.copy(is, os);
+        byte[] signed = os.toByteArray();
+        try {
+            verify("system.jks", "rsa", signed, false);
+        } catch (CryptoCmsException e) {
+            String message = e.getMessage();
+            assertEquals("PKCS7/CMS signature validation not possible: The content for which the hash-value must be calculated is missing in the PKCS7/CMS signed data instance. "
+                         + "Please check the configuration of the sender of the PKCS7/CMS signature.", message);
+            return;
+        }
+        fail("Exception expected");
+    }
+
+    @Test(expected = CryptoCmsNoCertificateForSignerInfosException.class)
+    public void verifyNoVerifierCerts() throws Exception {
+
+        byte[] signed = sign("Test Message", "system.jks", "SHA1withRSA", true, true, "rsa");
+
+        verify("system.jks", "wrongAlias", signed, false); // wrongAlias means
+                                                           // that no
+                                                           // certificates are
+                                                           // added to the
+                                                           // verifier keystore
+    }
+
+    @Test(expected = CryptoCmsFormatException.class)
+    public void verifyWrongFormat() throws Exception {
+
+        verify("system.jks", "rsa", "test".getBytes(), false);
+    }
+
+    @Test(expected = CryptoCmsFormatException.class)
+    public void verifyWrongFormatInHeader() throws Exception {
+
+        verifyContentWithSeparateSignature(new ByteArrayInputStream("ABCDEFG1ABCDEFG1ABCDEFG1".getBytes()), new ByteArrayInputStream("ABCDEFG1ABCDEFG1ABCDEFG1".getBytes()), "rsa");
+    }
+
+    @Test
+    public void verifyContentWithSeparateSignature() throws Exception {
+
+        InputStream message = new ByteArrayInputStream("Test Message".getBytes(StandardCharsets.UTF_8));
+
+        InputStream signature = this.getClass().getClassLoader().getResourceAsStream("detached_signature.binary");
+        assertNotNull(signature);
+
+        verifyContentWithSeparateSignature(message, signature, "rsa");
+    }
+
+    @Test(expected = CryptoCmsSignatureInvalidContentHashException.class)
+    public void verifyContentWithSeparateSignatureWrongContent() throws Exception {
+
+        InputStream message = new ByteArrayInputStream("Wrong Message".getBytes());
+
+        InputStream signature = this.getClass().getClassLoader().getResourceAsStream("detached_signature.binary");
+        assertNotNull(signature);
+
+        verifyContentWithSeparateSignature(message, signature, "rsa");
+
+    }
+
+    private void verifyContentWithSeparateSignature(InputStream content, InputStream signature, String alias) throws Exception {
+
+        DefaultSignedDataVerifierConfiguration verifierConf = getCryptoCmsSignedDataVerifierConf("system.jks", Collections.singletonList(alias), Boolean.FALSE);
+        SignedDataVerifier verifier = new SignedDataVerifierFromHeader(verifierConf);
+
+        Exchange exchange = ExchangeUtil.getExchange();
+        exchange.getIn().setBody(content);
+        exchange.getIn().setHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA, signature);
+        verifier.process(exchange);
+    }
+
+    @Test
+    public void verifyWithServeralAliases() throws Exception {
+        verifyDetachedSignatureWithKeystore("system.jks", "rsa", "rsa2");
+    }
+
+    @Test
+    public void verifyWithServeralAliasesOneWithNoEntryInKeystore() throws Exception {
+        verifyDetachedSignatureWithKeystore("system.jks", "noEntry", "rsa");
+    }
+
+    @Test(expected = CryptoCmsException.class)
+    public void verifyWithEmptyAlias() throws Exception {
+        verifyDetachedSignatureWithKeystore("system.jks", "");
+    }
+
+    @Test(expected = CryptoCmsNoCertificateForSignerInfoException.class)
+    public void verifyDetachedSignatureWithAliasNotFittingToSigner() throws Exception {
+        verifyDetachedSignatureWithKeystore("system.jks", "rsa2");
+    }
+
+    @Test(expected = CryptoCmsNoCertificateForSignerInfosException.class)
+    public void verifyDetachedSignatureWithAliasNotFittingToSignerWithVerifiyAllSignaturesFalse() throws Exception {
+        verifyDetachedSignatureWithKeystore("system.jks", Boolean.FALSE, "rsa2");
+    }
+
+    private void verifyDetachedSignatureWithKeystore(String keystoreName, String... aliases) throws FileNotFoundException, CryptoCmsException, Exception {
+        verifyDetachedSignatureWithKeystore(keystoreName, Boolean.TRUE, aliases);
+    }
+
+    private void verifyDetachedSignatureWithKeystore(String keystoreName, Boolean verifyAllSignatures, String... aliases)
+        throws FileNotFoundException, CryptoCmsException, Exception {
+
+        InputStream message = new ByteArrayInputStream("Test Message".getBytes(StandardCharsets.UTF_8));
+
+        assertNotNull(message);
+
+        DefaultSignedDataVerifierConfiguration verifierConf = getCryptoCmsSignedDataVerifierConf(keystoreName, Arrays.asList(aliases), Boolean.FALSE);
+        verifierConf.setVerifySignaturesOfAllSigners(verifyAllSignatures);
+
+        verifierConf.setSignedDataHeaderBase64(Boolean.TRUE);
+
+        SignedDataVerifier verifier = new SignedDataVerifierFromHeader(verifierConf);
+
+        InputStream signature = this.getClass().getClassLoader().getResourceAsStream("detached_signature.base64");
+        assertNotNull(signature);
+
+        Exchange exchange = ExchangeUtil.getExchange();
+        exchange.getIn().setBody(message);
+        exchange.getIn().setHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA, signature);
+        verifier.process(exchange);
+    }
+
+    @Test
+    public void signatureAndContentSeparatedExplicitMode() throws Exception {
+        String keystoreName = "system.jks";
+        String alias = "rsa";
+        KeyStoreParameters keystore = KeystoreUtil.getKeyStoreParameters(keystoreName);
+
+        DefaultSignerInfo signerInfo = new DefaultSignerInfo();
+        signerInfo.setIncludeCertificates(false); // without certificates,
+                                                  // optional default value is
+                                                  // true
+        signerInfo.setSignatureAlgorithm("SHA1withRSA"); // mandatory
+        signerInfo.setPrivateKeyAlias(alias);
+        signerInfo.setKeyStoreParameters(keystore);
+
+        SignedDataCreatorConfiguration config = new SignedDataCreatorConfiguration(new DefaultCamelContext());
+        config.setSigner(signerInfo);
+        config.setIncludeContent(false); // optional default value is true
+        config.setToBase64(Boolean.TRUE);
+        config.init();
+        SignedDataCreator signer = new SignedDataCreator(config);
+
+        String message = "Test Message";
+
+        Exchange exchange = ExchangeUtil.getExchange();
+
+        exchange.getIn().setBody(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)));
+        signer.process(exchange);
+
+        byte[] signature = exchange.getOut().getHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA, byte[].class);
+
+        DefaultSignedDataVerifierConfiguration verifierConf = getCryptoCmsSignedDataVerifierConf(keystoreName, Collections.singleton(alias), Boolean.FALSE);
+        verifierConf.setSignedDataHeaderBase64(Boolean.TRUE);
+
+        SignedDataVerifier verifier = new SignedDataVerifierFromHeader(verifierConf);
+
+        exchange = ExchangeUtil.getExchange();
+        exchange.getIn().setBody(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)));
+        exchange.getIn().setHeader(CryptoCmsConstants.CAMEL_CRYPTO_CMS_SIGNED_DATA, new ByteArrayInputStream(signature));
+        verifier.process(exchange);
+    }
+
+    private void signAndVerifyByDSASigAlgorithm(String sigAlgorithm) throws UnsupportedEncodingException, Exception {
+        // digest algorithm is calculated
+        signAndVerify("Test Message", "system.jks", sigAlgorithm, "dsa", true, false);
+    }
+
+    private void signAndVerifyByRSASigAlgorithm(String sigAlgorithm) throws UnsupportedEncodingException, Exception {
+        // digest algorithm is calculated
+        signAndVerify("Test Message", "system.jks", sigAlgorithm, "rsa", true, false);
+    }
+
+    @Test
+    public void testSigAlgorithmSHADSA() throws Exception {
+        signAndVerifyByDSASigAlgorithm("SHA1withDSA");
+    }
+
+    // SHA224withDSA
+    @Test
+    public void testSigAlgorithmSHA224withDSA() throws Exception {
+        signAndVerifyByDSASigAlgorithm("SHA224withDSA");
+    }
+
+    // SHA256withDSA
+    @Test
+    public void testSigAlgorithmSHA256withDSA() throws Exception {
+        signAndVerifyByDSASigAlgorithm("SHA256withDSA");
+    }
+
+    // SHA1withECDSA // ECSDSA keys not supported
+    @Test(expected = CryptoCmsException.class)
+    public void testSigAlgorithmSHA1withECDSA() throws Exception {
+        signAndVerifyByDSASigAlgorithm("SHA1withECDSA");
+    }
+
+    // MD2withRSA
+    @Test
+    public void testSigAlgorithmMD2withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("MD2withRSA");
+    }
+
+    // MD5/RSA
+    // MD2withRSA
+    @Test
+    public void testSigAlgorithmMD5withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("MD5withRSA");
+    }
+
+    // SHA/RSA
+    @Test
+    public void testSigAlgorithmSHAwithRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA1withRSA"); // SHA/RSA");
+    }
+
+    // SHA224/RSA
+    @Test
+    public void testSigAlgorithmSHA224withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA224withRSA");
+    }
+
+    // SHA256/RSA
+    @Test
+    public void testSigAlgorithmSHA256withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA256withRSA");
+    }
+
+    // SHA384/RSA
+    @Test
+    public void testSigAlgorithmSHA384withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA384withRSA");
+    }
+
+    // SHA512/RSA
+    @Test
+    public void testSigAlgorithmSHA512withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA512withRSA");
+    }
+
+    // RIPEMD160/RSA
+    @Test
+    public void testSigAlgorithmRIPEMD160withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("RIPEMD160withRSA");
+    }
+
+    // RIPEMD128/RSA
+    @Test
+    public void testSigAlgorithmRIPEMD128withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("RIPEMD128withRSA");
+    }
+
+    // RIPEMD256/RSA
+    @Test
+    public void testSigAlgorithmRIPEMD256withRSA() throws Exception {
+        signAndVerifyByRSASigAlgorithm("RIPEMD256withRSA");
+    }
+
+    @Test(expected = CryptoCmsInvalidKeyException.class)
+    public void testSigAlgorithmDoesnotFitToDSAPrivateKey() throws Exception {
+        signAndVerifyByDSASigAlgorithm("RIPEMD128withRSA");
+    }
+
+    @Test(expected = CryptoCmsInvalidKeyException.class)
+    public void testSigAlgorithmDoesnotFitToRSAPrivateKey() throws Exception {
+        signAndVerifyByRSASigAlgorithm("SHA224withDSA");
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/ExchangeUtil.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/ExchangeUtil.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/ExchangeUtil.java
new file mode 100644
index 0000000..f4eb11f
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/ExchangeUtil.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.util;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.impl.DefaultMessage;
+
+public final class ExchangeUtil {
+
+    private ExchangeUtil() {
+    }
+
+    public static Exchange getExchange() {
+        CamelContext context = new DefaultCamelContext();
+        Message in = new DefaultMessage(context);
+        Message out = new DefaultMessage(context);
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setIn(in);
+        exchange.setOut(out);
+        return exchange;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/KeystoreUtil.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/KeystoreUtil.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/KeystoreUtil.java
new file mode 100644
index 0000000..4381229
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/KeystoreUtil.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.util;
+
+import org.apache.camel.util.jsse.KeyStoreParameters;
+
+public final class KeystoreUtil {
+
+    private KeystoreUtil() {
+
+    }
+
+    public static KeyStoreParameters getKeyStoreParameters(String keystoreName) {
+        KeyStoreParameters keystorePas = new KeyStoreParameters();
+        keystorePas.setType("JCEKS");
+        keystorePas.setResource("keystore/" + keystoreName);
+        String pw;
+        if (keystoreName.startsWith("test")) {
+            pw = "abcd1234";
+        } else {
+            pw = "";
+        }
+        keystorePas.setPassword(pw);
+        return keystorePas;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b831203b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/TestAttributesGeneratorProvider.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/TestAttributesGeneratorProvider.java b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/TestAttributesGeneratorProvider.java
new file mode 100644
index 0000000..e7f60f0
--- /dev/null
+++ b/components/camel-crypto-cms/src/test/java/org/apache/camel/component/crypto/cms/util/TestAttributesGeneratorProvider.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.crypto.cms.util;
+
+import java.util.Hashtable;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.crypto.cms.common.AttributesGeneratorProvider;
+import org.apache.camel.component.crypto.cms.exception.CryptoCmsException;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERUTF8String;
+import org.bouncycastle.asn1.cms.Attribute;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.cms.CMSAttributeTableGenerator;
+import org.bouncycastle.cms.SimpleAttributeTableGenerator;
+
+public class TestAttributesGeneratorProvider implements AttributesGeneratorProvider {
+    
+
+    @Override
+    public CMSAttributeTableGenerator getAttributesGenerator(Exchange excange) throws CryptoCmsException {
+        Hashtable<ASN1ObjectIdentifier, Attribute> attrs = new Hashtable<>();
+
+        attrs.put(PKCSObjectIdentifiers.id_aa_contentHint, new Attribute(PKCSObjectIdentifiers.id_aa_contentHint, new DERSet(new DERUTF8String("Hint"))));
+        attrs.put(PKCSObjectIdentifiers.id_aa_receiptRequest, new Attribute(PKCSObjectIdentifiers.id_aa_receiptRequest, new DERSet(new DERUTF8String("Request"))));
+
+        AttributeTable attrTable = new AttributeTable(attrs);
+
+        return new SimpleAttributeTableGenerator(attrTable);
+    }
+
+}