You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/09/27 06:47:41 UTC
[camel] branch master updated: [CAMEL-12605] Added support for
encrypted and signed AS2 message
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new 2233a6a [CAMEL-12605] Added support for encrypted and signed AS2 message
2233a6a is described below
commit 2233a6a98a7fc23de6e451390c11f40c5d9d59f5
Author: William Collins <pu...@gmail.com>
AuthorDate: Wed Sep 26 14:27:25 2018 -0400
[CAMEL-12605] Added support for encrypted and signed AS2 message
---
.../camel/component/as2/api/AS2ClientManager.java | 37 ++++---
.../component/as2/api/entity/EntityParser.java | 2 +-
.../as2/api/entity/MultipartMimeEntity.java | 4 +
.../as2/api/entity/MultipartSignedEntity.java | 9 +-
.../camel/component/as2/api/AS2MessageTest.java | 116 +++++++++++++++++----
5 files changed, 126 insertions(+), 42 deletions(-)
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
index c99f341..5865efa 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
@@ -29,8 +29,10 @@ import org.apache.camel.component.as2.api.util.EntityUtils;
import org.apache.camel.component.as2.api.util.SigningUtils;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
+import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.util.Args;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
@@ -252,31 +254,38 @@ public class AS2ClientManager {
throw new HttpException("Failed to create EDI message entity", e);
}
switch (as2MessageStructure) {
- case PLAIN:
+ case PLAIN: {
applicationEDIEntity.setMainBody(true);
EntityUtils.setMessageEntity(request, applicationEDIEntity);
break;
- case SIGNED:
+ }
+ case SIGNED: {
AS2SignedDataGenerator gen = createSigningGenerator(httpContext);
// Create Multipart Signed Entity
- try {
- MultipartSignedEntity multipartSignedEntity = new MultipartSignedEntity(applicationEDIEntity, gen,
- AS2Charset.US_ASCII, AS2TransferEncoding.BASE64, true, null);
- multipartSignedEntity.setMainBody(true);
- EntityUtils.setMessageEntity(request, multipartSignedEntity);
- } catch (Exception e) {
- throw new HttpException("Failed to sign message", e);
- }
+ MultipartSignedEntity multipartSignedEntity = new MultipartSignedEntity(applicationEDIEntity, gen,
+ AS2Charset.US_ASCII, AS2TransferEncoding.BASE64, true, null);
+ multipartSignedEntity.setMainBody(true);
+ EntityUtils.setMessageEntity(request, multipartSignedEntity);
break;
- case ENCRYPTED:
+ }
+ case ENCRYPTED: {
CMSEnvelopedDataGenerator envelopedDataGenerator = createEncryptingGenerator(httpContext);
OutputEncryptor encryptor = createEncryptor(httpContext);
ApplicationPkcs7MimeEntity pkcs7MimeEntity = new ApplicationPkcs7MimeEntity(applicationEDIEntity, envelopedDataGenerator, encryptor, AS2TransferEncoding.BASE64, true);
EntityUtils.setMessageEntity(request, pkcs7MimeEntity);
break;
- case ENCRYPTED_SIGNED:
- // TODO : Add code here to add application/pkcs7-mime entity when encryption facility available.
+ }
+ case ENCRYPTED_SIGNED: {
+ AS2SignedDataGenerator signingGenrator = createSigningGenerator(httpContext);
+ MultipartSignedEntity multipartSignedEntity = new MultipartSignedEntity(applicationEDIEntity,
+ signingGenrator, AS2Charset.US_ASCII, AS2TransferEncoding.BASE64, false, null);
+
+ CMSEnvelopedDataGenerator envelopedDataGenerator = createEncryptingGenerator(httpContext);
+ OutputEncryptor encryptor = createEncryptor(httpContext);
+ ApplicationPkcs7MimeEntity pkcs7MimeEntity = new ApplicationPkcs7MimeEntity(multipartSignedEntity, envelopedDataGenerator, encryptor, AS2TransferEncoding.BASE64, true);
+ EntityUtils.setMessageEntity(request, pkcs7MimeEntity);
break;
+ }
default:
throw new HttpException("Unknown AS2 Message Structure");
}
@@ -292,7 +301,7 @@ public class AS2ClientManager {
httpContext.setAttribute(HTTP_RESPONSE, response);
return httpContext;
}
-
+
public AS2SignedDataGenerator createSigningGenerator(HttpCoreContext httpContext) throws HttpException {
Certificate[] certificateChain = httpContext.getAttribute(SIGNING_CERTIFICATE_CHAIN, Certificate[].class);
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
index fcb2431..aaf12e8 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
@@ -171,7 +171,7 @@ public final class EntityParser {
throw new HttpException("Failed to read start boundary for body part", e);
}
- if (!foundEndBoundary) {
+ if (!foundEndBoundary && boundary != null) {
throw new HttpException("Failed to find start boundary for body part");
}
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartMimeEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartMimeEntity.java
index 2b206f3..03f5835 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartMimeEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartMimeEntity.java
@@ -55,6 +55,10 @@ public abstract class MultipartMimeEntity extends MimeEntity {
protected MultipartMimeEntity() {
}
+
+ public String getBoundary() {
+ return boundary;
+ }
public void addPart(MimeEntity part) {
parts.add(part);
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartSignedEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartSignedEntity.java
index 6869b5f..3b0a6d2 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartSignedEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/MultipartSignedEntity.java
@@ -22,10 +22,8 @@ import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.util.Collection;
-import org.apache.camel.component.as2.api.AS2Header;
import org.apache.camel.component.as2.api.AS2SignedDataGenerator;
-import org.apache.http.entity.ContentType;
-import org.apache.http.message.BasicHeader;
+import org.apache.http.HttpException;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSProcessable;
@@ -38,10 +36,9 @@ import org.bouncycastle.util.Store;
public class MultipartSignedEntity extends MultipartMimeEntity {
- public MultipartSignedEntity(MimeEntity data, AS2SignedDataGenerator signer, String signatureCharSet, String signatureTransferEncoding, boolean isMainBody, String boundary) throws Exception {
+ public MultipartSignedEntity(MimeEntity data, AS2SignedDataGenerator signer, String signatureCharSet, String signatureTransferEncoding, boolean isMainBody, String boundary) throws HttpException {
super(null, isMainBody, boundary);
- ContentType contentType = signer.createMultipartSignedContentType(this.boundary);
- this.contentType = new BasicHeader(AS2Header.CONTENT_TYPE, contentType.toString());
+ setContentType(signer.createMultipartSignedContentType(this.boundary));
addPart(data);
ApplicationPkcs7SignatureEntity signature = new ApplicationPkcs7SignatureEntity(data, signer, signatureCharSet, signatureTransferEncoding, false);
addPart(signature);
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
index d9d3338..7d181aa 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
@@ -366,105 +366,105 @@ public class AS2MessageTest {
@Test
public void aes128CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES128_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES128_CBC);
}
@Test
public void aes192CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES192_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES192_CBC);
}
@Test
public void aes256CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES256_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES256_CBC);
}
@Test
public void aes128CcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES128_CCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES128_CCM);
}
@Test
public void aes192CcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES192_CCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES192_CCM);
}
@Test
public void aes256CcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES256_CCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES256_CCM);
}
@Test
public void aes128GcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES128_GCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES128_GCM);
}
@Test
public void aes192GcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES192_GCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES192_GCM);
}
@Test
public void aes256GcmEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.AES256_GCM);
+ envelopedMessageTest(AS2EncryptionAlgorithm.AES256_GCM);
}
@Test
public void camellia128CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.CAMELLIA128_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.CAMELLIA128_CBC);
}
@Test
public void camellia192CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.CAMELLIA192_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.CAMELLIA192_CBC);
}
@Test
public void camellia256CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.CAMELLIA256_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.CAMELLIA256_CBC);
}
@Test
public void cast5CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.CAST5_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.CAST5_CBC);
}
@Test
public void desCbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.DES_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.DES_CBC);
}
@Test
public void desEde3CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.DES_EDE3_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.DES_EDE3_CBC);
}
@Test
public void cost28147GcfbEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.GOST28147_GCFB);
+ envelopedMessageTest(AS2EncryptionAlgorithm.GOST28147_GCFB);
}
@Test
public void ideaCbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.IDEA_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.IDEA_CBC);
}
@Test
public void rc2CbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.RC2_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.RC2_CBC);
}
@Test
public void rc4EnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.RC4);
+ envelopedMessageTest(AS2EncryptionAlgorithm.RC4);
}
@Test
public void seedCbcEnvelopedMessageTest() throws Exception {
- envelopeddMessageTest(AS2EncryptionAlgorithm.SEED_CBC);
+ envelopedMessageTest(AS2EncryptionAlgorithm.SEED_CBC);
}
- public void envelopeddMessageTest(AS2EncryptionAlgorithm encryptionAlgorithm) throws Exception {
+ public void envelopedMessageTest(AS2EncryptionAlgorithm encryptionAlgorithm) throws Exception {
AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN,
TARGET_HOST, TARGET_PORT);
AS2ClientManager clientManager = new AS2ClientManager(clientConnection);
@@ -520,6 +520,80 @@ public class AS2MessageTest {
}
@Test
+ public void aes128CbcEnvelopedAndSignedMessageTest() throws Exception {
+ envelopedAndSignedMessageTest(AS2EncryptionAlgorithm.AES128_CBC);
+ }
+
+ public void envelopedAndSignedMessageTest(AS2EncryptionAlgorithm encryptionAlgorithm) throws Exception {
+ AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN,
+ TARGET_HOST, TARGET_PORT);
+ AS2ClientManager clientManager = new AS2ClientManager(clientConnection);
+
+ LOG.info("Key Algoritm: " + signingKP.getPrivate().getAlgorithm());
+
+ HttpCoreContext httpContext = clientManager.send(EDI_MESSAGE, REQUEST_URI, SUBJECT, FROM, AS2_NAME, AS2_NAME,
+ AS2MessageStructure.ENCRYPTED_SIGNED, ContentType.create(AS2MediaType.APPLICATION_EDIFACT, AS2Charset.US_ASCII),
+ null, certList.toArray(new Certificate[0]), signingKP.getPrivate(), DISPOSITION_NOTIFICATION_TO,
+ SIGNED_RECEIPT_MIC_ALGORITHMS, encryptionAlgorithm, certList.toArray(new Certificate[0]),
+ signingKP.getPrivate());
+
+ HttpRequest request = httpContext.getRequest();
+ assertEquals("Unexpected method value", METHOD, request.getRequestLine().getMethod());
+ assertEquals("Unexpected request URI value", REQUEST_URI, request.getRequestLine().getUri());
+ assertEquals("Unexpected HTTP version value", HttpVersion.HTTP_1_1,
+ request.getRequestLine().getProtocolVersion());
+
+ assertEquals("Unexpected subject value", SUBJECT, request.getFirstHeader(AS2Header.SUBJECT).getValue());
+ assertEquals("Unexpected from value", FROM, request.getFirstHeader(AS2Header.FROM).getValue());
+ assertEquals("Unexpected AS2 version value", AS2_VERSION,
+ request.getFirstHeader(AS2Header.AS2_VERSION).getValue());
+ assertEquals("Unexpected AS2 from value", AS2_NAME, request.getFirstHeader(AS2Header.AS2_FROM).getValue());
+ assertEquals("Unexpected AS2 to value", AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue());
+ assertTrue("Unexpected message id value",
+ request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"));
+ assertEquals("Unexpected target host value", TARGET_HOST + ":" + TARGET_PORT,
+ request.getFirstHeader(AS2Header.TARGET_HOST).getValue());
+ assertEquals("Unexpected user agent value", USER_AGENT,
+ request.getFirstHeader(AS2Header.USER_AGENT).getValue());
+ assertNotNull("Date value missing", request.getFirstHeader(AS2Header.DATE));
+ assertNotNull("Content length value missing", request.getFirstHeader(AS2Header.CONTENT_LENGTH));
+ assertTrue("Unexpected content type for message",
+ request.getFirstHeader(AS2Header.CONTENT_TYPE).getValue().startsWith(AS2MimeType.APPLICATION_PKCS7_MIME));
+
+ assertTrue("Request does not contain entity", request instanceof BasicHttpEntityEnclosingRequest);
+ HttpEntity entity = ((BasicHttpEntityEnclosingRequest) request).getEntity();
+ assertNotNull("Request does not contain entity", entity);
+ assertTrue("Unexpected request entity type", entity instanceof ApplicationPkcs7MimeEntity);
+ ApplicationPkcs7MimeEntity envelopedEntity = (ApplicationPkcs7MimeEntity) entity;
+ assertTrue("Entity not set as main body of request", envelopedEntity.isMainBody());
+
+ // Validated enveloped part.
+ MimeEntity encryptedEntity = envelopedEntity.getEncryptedEntity(signingKP.getPrivate());
+ assertTrue("Enveloped mime part incorrect type ", encryptedEntity instanceof MultipartSignedEntity);
+ MultipartSignedEntity multipartSignedEntity = (MultipartSignedEntity) encryptedEntity;
+ assertTrue("Unexpected content type for enveloped mime part",
+ multipartSignedEntity.getContentType().getValue().startsWith(AS2MediaType.MULTIPART_SIGNED));
+ assertFalse("Enveloped mime type set as main body of request", multipartSignedEntity.isMainBody());
+ assertTrue("Request contains invalid number of mime parts", multipartSignedEntity.getPartCount() == 2);
+
+ // Validated first mime part.
+ assertTrue("First mime part incorrect type ", multipartSignedEntity.getPart(0) instanceof ApplicationEDIFACTEntity);
+ ApplicationEDIFACTEntity ediEntity = (ApplicationEDIFACTEntity) multipartSignedEntity.getPart(0);
+ assertTrue("Unexpected content type for first mime part",
+ ediEntity.getContentType().getValue().startsWith(AS2MediaType.APPLICATION_EDIFACT));
+ assertFalse("First mime type set as main body of request", ediEntity.isMainBody());
+
+ // Validate second mime part.
+ assertTrue("Second mime part incorrect type ",
+ multipartSignedEntity.getPart(1) instanceof ApplicationPkcs7SignatureEntity);
+ ApplicationPkcs7SignatureEntity signatureEntity = (ApplicationPkcs7SignatureEntity) multipartSignedEntity.getPart(1);
+ assertTrue("Unexpected content type for second mime part",
+ signatureEntity.getContentType().getValue().startsWith(AS2MediaType.APPLICATION_PKCS7_SIGNATURE));
+ assertFalse("First mime type set as main body of request", signatureEntity.isMainBody());
+
+ }
+
+ @Test
public void signatureVerificationTest() throws Exception {
AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN,
TARGET_HOST, TARGET_PORT);