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 2015/09/24 16:43:59 UTC

camel git commit: CAMEL-9163: PGP Data Format: Support PGP Messages without Compressed Data packet

Repository: camel
Updated Branches:
  refs/for/master [created] ecbbeb74f


CAMEL-9163: PGP Data Format: Support PGP Messages without Compressed
Data packet

Change-Id: I6818cb2ee4777a7069a0760cae22c72074c63042


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ecbbeb74
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ecbbeb74
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ecbbeb74

Branch: refs/for/master
Commit: ecbbeb74f753ce81995171fb5d25f58930c22d26
Parents: 92c4a81
Author: Franz Forsthofer <fr...@sap.com>
Authored: Thu Sep 24 16:28:27 2015 +0200
Committer: Franz Forsthofer <fr...@sap.com>
Committed: Thu Sep 24 16:30:32 2015 +0200

----------------------------------------------------------------------
 .../converter/crypto/PGPDataFormatUtil.java     |  4 +-
 .../crypto/PGPKeyAccessDataFormat.java          | 63 +++++++++++++-------
 .../converter/crypto/PGPDataFormatTest.java     | 60 +++++++++++++++----
 3 files changed, 89 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ecbbeb74/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormatUtil.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormatUtil.java b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormatUtil.java
index 864337c..6f8f815 100644
--- a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormatUtil.java
+++ b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormatUtil.java
@@ -207,7 +207,6 @@ public final class PGPDataFormatUtil {
         return findPublicKeys(userids, forEncryption, pgpSec);
     }
 
-    @SuppressWarnings("unchecked")
     public static List<PGPPublicKey> findPublicKeys(List<String> useridParts, boolean forEncryption, PGPPublicKeyRingCollection pgpPublicKeyringCollection) {
         List<PGPPublicKey> result = new ArrayList<PGPPublicKey>(useridParts.size());
         for (Iterator<PGPPublicKeyRing> keyRingIter = pgpPublicKeyringCollection.getKeyRings(); keyRingIter.hasNext();) {
@@ -422,8 +421,7 @@ public final class PGPDataFormatUtil {
                 LOG.debug("User ID {} found in primary key with key ID {} containing one of the parts {}", new Object[] {
                     foundKeyUserIdForUserIdPart[0], primaryKey.getKeyID(), useridParts });
                 // add all signing keys
-                for (@SuppressWarnings("unchecked")
-                Iterator<PGPSecretKey> iterKey = keyring.getSecretKeys(); iterKey.hasNext();) {
+                for (Iterator<PGPSecretKey> iterKey = keyring.getSecretKeys(); iterKey.hasNext();) {
                     PGPSecretKey secKey = iterKey.next();
                     if (isSigningKey(secKey)) {
                         PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider)

http://git-wip-us.apache.org/repos/asf/camel/blob/ecbbeb74/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPKeyAccessDataFormat.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPKeyAccessDataFormat.java b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPKeyAccessDataFormat.java
index 88c0261..0d521a8 100644
--- a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPKeyAccessDataFormat.java
+++ b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPKeyAccessDataFormat.java
@@ -80,6 +80,8 @@ import org.slf4j.LoggerFactory;
  */
 public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat {
 
+    private static final Logger log = LoggerFactory.getLogger(PGPKeyAccessDataFormat.class);
+
     public static final String KEY_USERID = "CamelPGPDataFormatKeyUserid";
     public static final String KEY_USERIDS = "CamelPGPDataFormatKeyUserids";
     public static final String SIGNATURE_KEY_USERID = "CamelPGPDataFormatSignatureKeyUserid";
@@ -163,6 +165,8 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
     private int algorithm = SymmetricKeyAlgorithmTags.CAST5; // for encryption
 
     private int compressionAlgorithm = CompressionAlgorithmTags.ZIP; // for encryption
+    
+    private boolean withCompressedDataPacket = true; // for encryption
 
     private String signatureVerificationOption = "optional";
 
@@ -210,7 +214,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         return exchange.getIn().getHeader(Exchange.FILE_NAME, getFileName(), String.class);
     }
 
-    public void marshal(Exchange exchange, Object graph, OutputStream outputStream) throws Exception {
+    public void marshal(Exchange exchange, Object graph, OutputStream outputStream) throws Exception { //NOPMD
         List<String> userids = determineEncryptionUserIds(exchange);
         List<PGPPublicKey> keys = publicKeyAccessor.getEncryptionKeys(exchange, userids);
         if (keys.isEmpty()) {
@@ -233,9 +237,15 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         }
         OutputStream encOut = encGen.open(outputStream, new byte[BUFFER_SIZE]);
 
-        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(findCompressionAlgorithm(exchange));
-        OutputStream comOut = new BufferedOutputStream(comData.open(encOut));
-
+        OutputStream comOut;
+        if (withCompressedDataPacket) {
+            PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(findCompressionAlgorithm(exchange));
+            comOut = new BufferedOutputStream(comData.open(encOut));
+        } else {
+            comOut = encOut;
+            LOG.debug("No Compressed Data packet is added");  
+        }
+            
         List<PGPSignatureGenerator> sigGens = createSignatureGenerator(exchange, comOut);
 
         PGPLiteralDataGenerator litData = new PGPLiteralDataGenerator();
@@ -311,7 +321,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         return result;
     }
 
-    protected List<PGPSignatureGenerator> createSignatureGenerator(Exchange exchange, OutputStream out) throws Exception {
+    protected List<PGPSignatureGenerator> createSignatureGenerator(Exchange exchange, OutputStream out) throws Exception { //NOPMD
 
         if (secretKeyAccessor == null) {
             return null;
@@ -345,7 +355,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
     }
 
     @SuppressWarnings("resource")
-    public Object unmarshal(Exchange exchange, InputStream encryptedStream) throws Exception {
+    public Object unmarshal(Exchange exchange, InputStream encryptedStream) throws Exception { //NOPMD
         if (encryptedStream == null) {
             return null;
         }
@@ -361,10 +371,16 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         try {
             in = PGPUtil.getDecoderStream(encryptedStream);
             encData = getDecryptedData(exchange, in);
-            uncompressedData = getUncompressedData(encData);
-            PGPObjectFactory pgpFactory = new PGPObjectFactory(uncompressedData, new BcKeyFingerprintCalculator());
+            PGPObjectFactory pgpFactory = new PGPObjectFactory(encData, new BcKeyFingerprintCalculator());
             Object object = pgpFactory.nextObject();
-
+            if (object instanceof PGPCompressedData) {
+                PGPCompressedData comData = (PGPCompressedData) object;
+                uncompressedData = comData.getDataStream();
+                pgpFactory = new PGPObjectFactory(uncompressedData, new BcKeyFingerprintCalculator());
+                object = pgpFactory.nextObject();
+            } else {
+                log.debug("PGP Message does not contain a Compressed Data Packet");
+            }
             PGPOnePassSignature signature;
             if (object instanceof PGPOnePassSignatureList) {
                 signature = getSignature(exchange, (PGPOnePassSignatureList) object);
@@ -418,17 +434,6 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         }
     }
 
-    private InputStream getUncompressedData(InputStream encData) throws IOException, PGPException {
-        PGPObjectFactory pgpFactory = new PGPObjectFactory(encData, new BcKeyFingerprintCalculator());
-        Object compObj = pgpFactory.nextObject();
-        if (!(compObj instanceof PGPCompressedData)) {
-            throw getFormatException();
-        }
-        PGPCompressedData comData = (PGPCompressedData) compObj;
-        InputStream uncompressedData = comData.getDataStream();
-        return uncompressedData;
-    }
-
     private InputStream getDecryptedData(Exchange exchange, InputStream encryptedStream) throws Exception, PGPException {
         PGPObjectFactory pgpFactory = new PGPObjectFactory(encryptedStream, new BcKeyFingerprintCalculator());
         Object firstObject = pgpFactory.nextObject();
@@ -489,7 +494,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         return new IllegalArgumentException(
                 "The input message body has an invalid format. The PGP decryption/verification processor expects a sequence of PGP packets of the form "
                         + "(entries in brackets are optional and ellipses indicate repetition, comma represents  sequential composition, and vertical bar separates alternatives): "
-                        + "Public Key Encrypted Session Key ..., Symmetrically Encrypted Data | Sym. Encrypted and Integrity Protected Data, Compressed Data, (One Pass Signature ...,) "
+                        + "Public Key Encrypted Session Key ..., Symmetrically Encrypted Data | Sym. Encrypted and Integrity Protected Data, (Compressed Data,) (One Pass Signature ...,) "
                         + "Literal Data, (Signature ...,)");
     }
 
@@ -709,6 +714,18 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
         return signatureVerificationOption;
     }
 
+    public boolean isWithCompressedDataPacket() {
+        return withCompressedDataPacket;
+    }
+
+    /** Indicator that Compressed Data packet shall be added during encryption.
+     * The default value is true.
+     * If <tt>false</tt> then the compression algorithm (see {@link #setCompressionAlgorithm(int)} is ignored. 
+     */
+    public void setWithCompressedDataPacket(boolean withCompressedDataPacket) {
+        this.withCompressedDataPacket = withCompressedDataPacket;
+    }
+
     /**
      * Signature verification option. Controls the behavior for the signature
      * verification during unmarshaling. Possible values are
@@ -762,7 +779,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
     }
 
     @Override
-    protected void doStart() throws Exception {
+    protected void doStart() throws Exception { //NOPMD
         if (Security.getProvider(BC) == null && BC.equals(getProvider())) {
             LOG.debug("Adding BouncyCastleProvider as security provider");
             Security.addProvider(new BouncyCastleProvider());
@@ -772,7 +789,7 @@ public class PGPKeyAccessDataFormat extends ServiceSupport implements DataFormat
     }
 
     @Override
-    protected void doStop() throws Exception {
+    protected void doStop() throws Exception { //NOPMD
         // noop
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ecbbeb74/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatTest.java
----------------------------------------------------------------------
diff --git a/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatTest.java b/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatTest.java
index f24d40e..565496b 100644
--- a/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatTest.java
+++ b/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatTest.java
@@ -298,17 +298,19 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
     }
 
     @Test
-    public void testExceptionDecryptorIncorrectInputNoCompression() throws Exception {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
-        createEncryptedNonCompressedData(bos, PUB_KEY_RING_SUBKEYS_FILE_NAME);
-
-        MockEndpoint mock = getMockEndpoint("mock:exception");
-        mock.expectedMessageCount(1);
-        template.sendBody("direct:subkeyUnmarshal", bos.toByteArray());
-        assertMockEndpointsSatisfied();
-
-        checkThrownException(mock, IllegalArgumentException.class, null, "The input message body has an invalid format.");
+    public void testEncryptSignWithoutCompressedDataPacket() throws Exception {
+        
+        doRoundTripEncryptionTests("direct:encrypt-sign-without-compressed-data-packet");
+//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+//
+////        createEncryptedNonCompressedData(bos, PUB_KEY_RING_SUBKEYS_FILE_NAME);
+//
+//        MockEndpoint mock = getMockEndpoint("mock:exception");
+//        mock.expectedMessageCount(1);
+//        template.sendBody("direct:encrypt-sign-without-compressed-data-packet", bos.toByteArray());
+//        assertMockEndpointsSatisfied();
+//
+//        //checkThrownException(mock, IllegalArgumentException.class, null, "The input message body has an invalid format.");
     }
 
     @Test
@@ -710,7 +712,41 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
                         .to("mock:unencrypted");
 
             }
-        } };
+        }, new RouteBuilder() {
+            public void configure() throws Exception {
+        
+                // START SNIPPET: pgp-encrypt-sign-without-compressed-data-packet
+                PGPDataFormat pgpEncryptSign = new PGPDataFormat();
+                pgpEncryptSign.setKeyUserid(getKeyUserId());
+                pgpEncryptSign.setSignatureKeyRing(getSecKeyRing());
+                pgpEncryptSign.setSignatureKeyUserid(getKeyUserId());
+                pgpEncryptSign.setSignaturePassword(getKeyPassword());
+                pgpEncryptSign.setProvider(getProvider());
+                pgpEncryptSign.setAlgorithm(SymmetricKeyAlgorithmTags.BLOWFISH);
+                pgpEncryptSign.setHashAlgorithm(HashAlgorithmTags.RIPEMD160);
+                // without compressed data packet
+                pgpEncryptSign.setWithCompressedDataPacket(false);
+        
+                PGPDataFormat pgpVerifyAndDecryptByteArray = new PGPDataFormat();
+                pgpVerifyAndDecryptByteArray.setPassphraseAccessor(getPassphraseAccessor());
+                pgpVerifyAndDecryptByteArray.setEncryptionKeyRing(getSecKeyRing());
+                pgpVerifyAndDecryptByteArray.setProvider(getProvider());
+                // restrict verification to public keys with certain User ID
+                pgpVerifyAndDecryptByteArray.setSignatureKeyUserids(getSignatureKeyUserIds());
+                pgpVerifyAndDecryptByteArray.setSignatureVerificationOption(PGPKeyAccessDataFormat.SIGNATURE_VERIFICATION_OPTION_REQUIRED);
+        
+                from("direct:encrypt-sign-without-compressed-data-packet").streamCaching()
+                // encryption key ring can also be set as header
+                        .setHeader(PGPDataFormat.ENCRYPTION_KEY_RING).constant(getPublicKeyRing()).marshal(pgpEncryptSign)
+                        // it is recommended to remove the header immediately when it is no longer needed
+                        .removeHeader(PGPDataFormat.ENCRYPTION_KEY_RING).to("mock:encrypted")
+                        // signature key ring can also be set as header
+                        .setHeader(PGPDataFormat.SIGNATURE_KEY_RING).constant(getPublicKeyRing()).unmarshal(pgpVerifyAndDecryptByteArray)
+                        // it is recommended to remove the header immediately when it is no longer needed
+                        .removeHeader(PGPDataFormat.SIGNATURE_KEY_RING).to("mock:unencrypted");
+                // END SNIPPET: pgp-encrypt-sign-without-compressed-data-packet
+            }
+        }};
     }
 
     public static byte[] getPublicKeyRing() throws Exception {