[ 
https://issues.apache.org/jira/browse/CAMEL-12605?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16591220#comment-16591220
 ] 

ASF GitHub Bot commented on CAMEL-12605:
----------------------------------------

oscerd closed pull request #2493: CAMEL-12605] Added encrypt/decrypt logic for 
enveloped entities
URL: https://github.com/apache/camel/pull/2493
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 e0812898c2a..4e22e7baf77 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
@@ -275,4 +275,20 @@ public AS2SignedDataGenerator 
createSigningGenerator(HttpCoreContext httpContext
 
     }
 
+    public AS2SignedDataGenerator createEncryptingGenerator(HttpCoreContext 
httpContext) throws HttpException {
+
+        Certificate[] certificateChain = 
httpContext.getAttribute(SIGNING_CERTIFICATE_CHAIN, Certificate[].class);
+        if (certificateChain == null) {
+            throw new HttpException("Signing certificate chain missing");
+        }
+
+        PrivateKey privateKey = httpContext.getAttribute(SIGNING_PRIVATE_KEY, 
PrivateKey.class);
+        if (privateKey == null) {
+            throw new HttpException("Signing private key missing");
+        }
+
+        return SigningUtils.createSigningGenerator(certificateChain, 
privateKey);
+
+    }
+
 }
diff --git 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2SignedDataGenerator.java
 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2SignedDataGenerator.java
index f52429a4d7f..1ab44c061c4 100644
--- 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2SignedDataGenerator.java
+++ 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2SignedDataGenerator.java
@@ -108,6 +108,7 @@ public AS2SignedDataGenerator() {
     /**
      * Creates a <code>multipart/signed</code> content type containing the 
algorithms used by this generator.
      *
+     * @param boundary - boundary to use to demarcate content.
      * @return A <code>multipart/signed</code> content type
      */
     public ContentType createMultipartSignedContentType(String boundary) {
diff --git 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7Mime.java
 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
similarity index 72%
rename from 
components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7Mime.java
rename to 
components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
index 88d70b673ad..b61b440244b 100644
--- 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7Mime.java
+++ 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
@@ -16,38 +16,50 @@
  */
 package org.apache.camel.component.as2.api.entity;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.security.PrivateKey;
+import java.util.Collection;
+import java.util.Iterator;
 
 import org.apache.camel.component.as2.api.AS2Charset;
 import org.apache.camel.component.as2.api.AS2Header;
 import org.apache.camel.component.as2.api.CanonicalOutputStream;
+import org.apache.camel.component.as2.api.io.AS2SessionInputBuffer;
+import org.apache.camel.component.as2.api.util.EntityUtils;
 import org.apache.http.Header;
 import org.apache.http.HeaderIterator;
 import org.apache.http.HttpException;
 import org.apache.http.entity.ContentType;
+import org.apache.http.impl.io.HttpTransportMetricsImpl;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.Args;
 import org.bouncycastle.cms.CMSEnvelopedData;
 import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
 import org.bouncycastle.cms.CMSProcessableByteArray;
 import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cms.Recipient;
+import org.bouncycastle.cms.RecipientInformation;
+import org.bouncycastle.cms.RecipientInformationStore;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
 import org.bouncycastle.operator.OutputEncryptor;
 
-public class ApplicationPkcs7Mime extends MimeEntity {
+public class ApplicationPkcs7MimeEntity extends MimeEntity {
     
     private static final String CONTENT_DISPOSITION = "attachment; 
filename=\"smime.p7m\"";
     
     private byte[] encryptedData;
     
-    public ApplicationPkcs7Mime(MimeEntity entity2Encrypt,
+    public ApplicationPkcs7MimeEntity(MimeEntity entity2Encrypt,
                                 CMSEnvelopedDataGenerator dataGenerator,
                                 OutputEncryptor encryptor,
                                 String encryptedContentTransferEncoding,
                                 boolean isMainBody)
             throws HttpException {
-        setContentType(ContentType.create("application/pkcs7-mime", new 
BasicNameValuePair("smime-type", "enveloped-datat"),
+        setContentType(ContentType.create("application/pkcs7-mime", new 
BasicNameValuePair("smime-type", "enveloped-data"),
                 new BasicNameValuePair("name", "smime.p7m")));
         setContentTransferEncoding(encryptedContentTransferEncoding);
         addHeader(AS2Header.CONTENT_DISPOSITION, CONTENT_DISPOSITION);
@@ -59,7 +71,7 @@ public ApplicationPkcs7Mime(MimeEntity entity2Encrypt,
         }
     }
     
-    public ApplicationPkcs7Mime(byte[] encryptedData, String 
encryptedContentTransferEncoding, boolean isMainBody) {
+    public ApplicationPkcs7MimeEntity(byte[] encryptedData, String 
encryptedContentTransferEncoding, boolean isMainBody) {
         this.encryptedData = Args.notNull(encryptedData, "encryptedData");
         
         setContentType(ContentType.create("application/pkcs7-mime", new 
BasicNameValuePair("smime-type", "enveloped-datat"),
@@ -88,15 +100,30 @@ public void writeTo(OutputStream outstream) throws 
IOException {
             }
         }
         
+        // Write out signed data.
+        String transferEncoding = getContentTransferEncoding() == null ? null 
: getContentTransferEncoding().getValue();
+        try (OutputStream transferEncodedStream = EntityUtils.encode(ncos, 
transferEncoding)) {
+
+            transferEncodedStream.write(encryptedData);
+        } catch (Exception e) {
+            throw new IOException("Failed to write to output stream", e);
+        }
+    }
+    
+    public MimeEntity getEncryptedEntity(PrivateKey privateKey) {
+        
+        return EntityParser.parseEnvelopedEntity(encryptedData, privateKey);
+        
+        
     }
     
-    private byte[] createEncryptedData(MimeEntity entity2Encrypt, 
CMSEnvelopedDataGenerator dataGenerator, OutputEncryptor encryptor) throws 
Exception {
+    private byte[] createEncryptedData(MimeEntity entity2Encrypt, 
CMSEnvelopedDataGenerator envelopedDataGenerator, OutputEncryptor encryptor) 
throws Exception {
         try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
             entity2Encrypt.writeTo(bos);
             bos.flush();
 
             CMSTypedData contentData = new 
CMSProcessableByteArray(bos.toByteArray());
-            CMSEnvelopedData  envelopedData = 
dataGenerator.generate(contentData, encryptor);
+            CMSEnvelopedData  envelopedData = 
envelopedDataGenerator.generate(contentData, encryptor);
             return envelopedData.getEncoded();
         } catch (Exception e) {
             throw new Exception("", e);
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 4e86d148a85..b2c3f46f1d7 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
@@ -16,10 +16,15 @@
  */
 package org.apache.camel.component.as2.api.entity;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
+import java.security.PrivateKey;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.camel.component.as2.api.AS2Charset;
@@ -44,6 +49,11 @@
 import org.apache.http.message.ParserCursor;
 import org.apache.http.util.Args;
 import org.apache.http.util.CharArrayBuffer;
+import org.bouncycastle.cms.CMSEnvelopedData;
+import org.bouncycastle.cms.Recipient;
+import org.bouncycastle.cms.RecipientInformation;
+import org.bouncycastle.cms.RecipientInformationStore;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -164,7 +174,71 @@ public static void skipToBoundary(AS2SessionInputBuffer 
inbuffer, String boundar
         }
 
     }
+    
+    public static MimeEntity parseEnvelopedEntity(byte[] envelopedContent, 
PrivateKey privateKey) {
+        
+        try {
+            byte[] decryptedContent = decryptData(envelopedContent, 
privateKey);
+            
+            InputStream is = new ByteArrayInputStream(decryptedContent);
+            AS2SessionInputBuffer inbuffer = new AS2SessionInputBuffer(new 
HttpTransportMetricsImpl(), DEFAULT_BUFFER_SIZE);
+            inbuffer.bind(is);
+
+            // Read Text Report Body Part Headers
+            Header[] headers = AbstractMessageParser.parseHeaders(inbuffer, 
-1, -1, BasicLineParser.INSTANCE,
+                    new ArrayList<CharArrayBuffer>());
+
+            // Get Content-Type and Content-Transfer-Encoding
+            ContentType envelopedEntityContentType = null;
+            String envelopedEntityContentTransferEncoding = null;
+            for (Header header : headers) {
+                switch (header.getName()) {
+                case AS2Header.CONTENT_TYPE:
+                    envelopedEntityContentType = 
ContentType.parse(header.getValue());
+                    break;
+                case AS2Header.CONTENT_TRANSFER_ENCODING:
+                    envelopedEntityContentTransferEncoding = header.getValue();
+                    break;
+                default:
+                    continue;
+                }
+            }
+            if (envelopedEntityContentType == null) {
+                throw new HttpException("Failed to find Content-Type header in 
enveloped entity");
+            }
+
+            MimeEntity entity = parseEntityBody(inbuffer, null, 
envelopedEntityContentType, envelopedEntityContentTransferEncoding, headers);
+            entity.removeAllHeaders();
+            entity.setHeaders(headers);
+            
+            return entity;
+        } catch (Exception e) {
+            return null;
+        }
+    }
 
+    public static byte[] decryptData(byte[] encryptedData, PrivateKey 
privateKey) throws Exception {
+        // Create enveloped data from encrypted data
+        CMSEnvelopedData cmsEnvelopedData = new 
CMSEnvelopedData(encryptedData);
+        
+        // Extract recipient information form enveloped data.
+        RecipientInformationStore recipientsInformationStore = 
cmsEnvelopedData.getRecipientInfos();
+        Collection<RecipientInformation> recipients = 
recipientsInformationStore.getRecipients();
+        Iterator<RecipientInformation> it = recipients.iterator();
+        
+        // Decrypt if enveloped data contains recipient information
+        if (it.hasNext()) {
+            // Create recipient from private key.
+            Recipient recipient = new 
JceKeyTransEnvelopedRecipient(privateKey);
+
+            // Extract decrypted data from recipient information
+            RecipientInformation recipientInfo = it.next();
+            return recipientInfo.getContent(recipient);
+        }
+        
+        return null;
+    }
+    
     public static void parseMultipartSignedEntity(HttpMessage message)
             throws HttpException {
         MultipartSignedEntity multipartSignedEntity = null;
@@ -763,6 +837,39 @@ public static ApplicationPkcs7SignatureEntity 
parseApplicationPkcs7SignatureEnti
         }
     }
 
+    public static ApplicationPkcs7MimeEntity 
parseApplicationPkcs7MimeEntityBody(AS2SessionInputBuffer inbuffer,
+                                                                               
       String boundary,
+                                                                               
       ContentType contentType,
+                                                                               
       String contentTransferEncoding)
+            throws ParseException {
+
+        CharsetDecoder previousDecoder = inbuffer.getCharsetDecoder();
+
+        try {
+            Charset charset = contentType.getCharset();
+            if (charset == null) {
+                charset = Charset.forName(AS2Charset.US_ASCII);
+            }
+            CharsetDecoder charsetDecoder = charset.newDecoder();
+
+            inbuffer.setCharsetDecoder(charsetDecoder);
+
+            String pkcs7EncryptedBodyContent = parseBodyPartText(inbuffer, 
boundary);
+
+            byte[] encryptedContent = 
EntityUtils.decode(pkcs7EncryptedBodyContent.getBytes(charset), 
contentTransferEncoding);
+
+            ApplicationPkcs7MimeEntity applicationPkcs7MimeEntity = new 
ApplicationPkcs7MimeEntity(
+                    encryptedContent, contentTransferEncoding, false);
+            return applicationPkcs7MimeEntity;
+        } catch (Exception e) {
+            ParseException parseException = new ParseException("failed to 
parse PKCS7 Mime entity");
+            parseException.initCause(e);
+            throw parseException;
+        } finally {
+            inbuffer.setCharsetDecoder(previousDecoder);
+        }
+    }
+
     public static String parseBodyPartText(final AS2SessionInputBuffer 
inbuffer,
                                            final String boundary)
             throws IOException {
diff --git 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/AS2Utils.java
 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/AS2Utils.java
index d4c31616a6d..00482e5c761 100644
--- 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/AS2Utils.java
+++ 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/AS2Utils.java
@@ -62,7 +62,7 @@ private AS2Utils() {
      * Validates if the given <code>name</code> is a valid AS2 Name
      *
      * @param name - the name to validate.
-     * @throws InvalidAS2NameException
+     * @throws InvalidAS2NameException - If <code>name</code> is invalid.
      */
     public static void validateAS2Name(String name) throws 
InvalidAS2NameException {
         Matcher matcher = AS_NAME_PATTERN.matcher(name);
@@ -126,7 +126,7 @@ public static String printMessage(HttpMessage message) 
throws IOException {
      *            - the stream printed to.
      * @param request
      *            - the request printed.
-     * @throws IOException
+     * @throws IOException - If failed to print request.
      */
     public static void printRequest(PrintStream out, HttpRequest request) 
throws IOException {
         // Print request line
@@ -152,7 +152,7 @@ public static void printRequest(PrintStream out, 
HttpRequest request) throws IOE
      *
      * @param out - the stream printed to.
      * @param message - the request printed.
-     * @throws IOException
+     * @throws IOException - If failed to print message.
      */
     public static void printMessage(PrintStream out, HttpMessage message) 
throws IOException {
         // Print request line


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> Enhance the AS2 Component to send and receive encrypted AS2 messages
> --------------------------------------------------------------------
>
>                 Key: CAMEL-12605
>                 URL: https://issues.apache.org/jira/browse/CAMEL-12605
>             Project: Camel
>          Issue Type: Improvement
>    Affects Versions: 2.23.0
>            Reporter: William Collins
>            Assignee: William Collins
>            Priority: Major
>
> Enhance the AS2 Component to support encrypted AS2 messages per RFC4130



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to