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