Updated Branches:
  refs/heads/camel-2.12.x 882f41f56 -> b7e6261f4

CAMEL-6911. Support encryption using multiple keys


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

Branch: refs/heads/camel-2.12.x
Commit: 5dd309b7a97f15bbf83a5814d7dc66b152e975da
Parents: 882f41f
Author: Hadrian Zbarcea <hzbar...@gmail.com>
Authored: Fri Nov 22 18:06:20 2013 -0500
Committer: Hadrian Zbarcea <hzbar...@gmail.com>
Committed: Fri Nov 22 18:06:55 2013 -0500

----------------------------------------------------------------------
 .../camel/converter/crypto/PGPDataFormat.java   | 199 ++++++++++++++-----
 .../converter/crypto/PGPDataFormatUtil.java     |  60 ++++--
 .../crypto/PGPDataFormatDynamicTest.java        |  26 ++-
 .../converter/crypto/PGPDataFormatTest.java     |  67 ++++---
 .../crypto/SpringPGPDataFormatTest.xml          |   1 +
 5 files changed, 249 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/5dd309b7/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java
----------------------------------------------------------------------
diff --git 
a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java
 
b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java
index db3deb0..985e80d 100644
--- 
a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java
+++ 
b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java
@@ -26,7 +26,10 @@ import java.security.NoSuchProviderException;
 import java.security.SecureRandom;
 import java.security.Security;
 import java.security.SignatureException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.converter.stream.CachedOutputStream;
@@ -78,6 +81,7 @@ public class PGPDataFormat extends ServiceSupport implements 
DataFormat {
     public static final String KEY_FILE_NAME = "CamelPGPDataFormatKeyFileName";
     public static final String ENCRYPTION_KEY_RING = 
"CamelPGPDataFormatEncryptionKeyRing";
     public static final String KEY_USERID = "CamelPGPDataFormatKeyUserid";
+    public static final String KEY_USERIDS = "CamelPGPDataFormatKeyUserids";
     public static final String KEY_PASSWORD = "CamelPGPDataFormatKeyPassword";
     public static final String SIGNATURE_KEY_FILE_NAME = 
"CamelPGPDataFormatSignatureKeyFileName";
     public static final String SIGNATURE_KEY_RING = 
"CamelPGPDataFormatSignatureKeyRing";
@@ -85,6 +89,7 @@ public class PGPDataFormat extends ServiceSupport implements 
DataFormat {
     public static final String SIGNATURE_KEY_PASSWORD = 
"CamelPGPDataFormatSignatureKeyPassword";
     public static final String ENCRYPTION_ALGORITHM = 
"CamelPGPDataFormatEncryptionAlgorithm";
     public static final String SIGNATURE_HASH_ALGORITHM = 
"CamelPGPDataFormatSignatureHashAlgorithm";
+    public static final String COMPRESSION_ALGORITHM = 
"CamelPGPDataFormatCompressionAlgorithm";
 
     private static final Logger LOG = 
LoggerFactory.getLogger(PGPDataFormat.class);
 
@@ -95,43 +100,30 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     private String provider = BC;
 
     // encryption / decryption key info (required)
-    private String keyUserid;
-    private String password;
+    private String keyUserid; // only for encryption
+    //in addition you can specify further User IDs, in this case the symmetric 
key is encrypted by several public keys corresponding to the User Ids
+    private List<String> keyUserids; //only for encryption;
+    private String password; // only for decryption
     private String keyFileName;
     // alternatively to the file name you can specify the key ring as byte 
array
     private byte[] encryptionKeyRing;
 
     // signature / verification key info (optional)
-    private String signatureKeyUserid;
-    private String signaturePassword;
+    private String signatureKeyUserid; // for encryption
+    private String signaturePassword; // for encryption
     private String signatureKeyFileName;
     // alternatively to the signature key file name you can specify the 
signature key ring as byte array
     private byte[] signatureKeyRing;
 
-    private boolean armored;
-    private boolean integrity = true;
+    private boolean armored; // for encryption
+    private boolean integrity = true; // for encryption
 
-    /**
-     * Digest algorithm for signing (marshal). Possible values are defined in
-     * {@link HashAlgorithmTags}. Default value is SHA1.
-     */
-    private int hashAlgorithm = HashAlgorithmTags.SHA1;
+    private int hashAlgorithm = HashAlgorithmTags.SHA1; // for encryption
 
-    /**
-     * Symmetric key algorithm for encryption (marschal). Possible values are
-     * defined in {@link SymmetricKeyAlgorithmTags}. Default value is CAST5.
-     */
-    private int algorithm = SymmetricKeyAlgorithmTags.CAST5;
+    private int algorithm = SymmetricKeyAlgorithmTags.CAST5; // for encryption
+
+    private int compressionAlgorithm = CompressionAlgorithmTags.ZIP; // for 
encryption
 
-    /**
-     * If no passphrase can be found from the parameter <tt>password</tt> or
-     * <tt>signaturePassword</tt> or from the header
-     * {@link #SIGNATURE_KEY_PASSWORD} or {@link #KEY_PASSWORD} then we try to
-     * get the password from the passphrase accessor. This is especially useful
-     * in the decrypt case, where we chose the private key according to the key
-     * Id stored in the encrypted data. So in this case we do not know the user
-     * Id in advance.
-     */
     private PGPPassphraseAccessor passphraseAccessor;
 
     public PGPDataFormat() {
@@ -149,16 +141,19 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return exchange.getIn().getHeader(KEY_USERID, getKeyUserid(), 
String.class);
     }
 
+    @SuppressWarnings("unchecked")
+    protected List<String> findKeyUserids(Exchange exchange) {
+        return exchange.getIn().getHeader(KEY_USERIDS, getKeyUserids(), 
List.class);
+    }
+
     protected String findKeyPassword(Exchange exchange) {
-        String keyPassword = exchange.getIn().getHeader(KEY_PASSWORD, 
getPassword(), String.class);
-        if (keyPassword != null) {
-            return keyPassword;
-        }
-        if (passphraseAccessor != null) {
-            return passphraseAccessor.getPassphrase(findKeyUserid(exchange));
-        } else {
-            return null;
-        }
+        return exchange.getIn().getHeader(KEY_PASSWORD, getPassword(), 
String.class);
+        // the following lines are not needed because the passphrase accessor 
is taken into account later in the decryption case
+        //        if (passphraseAccessor != null) {
+        //            return 
passphraseAccessor.getPassphrase(findKeyUserid(exchange));
+        //        } else {
+        //            return null;
+        //        }
     }
 
     protected String findSignatureKeyFileName(Exchange exchange) {
@@ -185,6 +180,10 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         }
     }
 
+    protected int findCompressionAlgorithm(Exchange exchange) {
+        return exchange.getIn().getHeader(COMPRESSION_ALGORITHM, 
getCompressionAlgorithm(), Integer.class);
+    }
+
     protected int findAlgorithm(Exchange exchange) {
         return exchange.getIn().getHeader(ENCRYPTION_ALGORITHM, 
getAlgorithm(), Integer.class);
     }
@@ -194,10 +193,12 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     public void marshal(Exchange exchange, Object graph, OutputStream 
outputStream) throws Exception {
-        PGPPublicKey key = 
PGPDataFormatUtil.findPublicKey(exchange.getContext(), 
findKeyFileName(exchange),
-                findEncryptionKeyRing(exchange), findKeyUserid(exchange), 
true);
-        if (key == null) {
-            throw new IllegalArgumentException("Public key is null, cannot 
proceed");
+        List<String> userids = determineEncryptionUserIds(exchange);
+        List<PGPPublicKey> keys = 
PGPDataFormatUtil.findPublicKeys(exchange.getContext(), 
findKeyFileName(exchange),
+                findEncryptionKeyRing(exchange), userids, true);
+        if (keys.isEmpty()) {
+            throw new IllegalArgumentException("Cannot PGP encrypt message. No 
public encryption key found for the User Ids " + userids
+                    + " in the public keyring. Either specify other User IDs 
or add correct public keys to the keyring.");
         }
 
         InputStream input = ExchangeHelper.convertToMandatoryType(exchange, 
InputStream.class, graph);
@@ -208,10 +209,13 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
 
         PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(new 
JcePGPDataEncryptorBuilder(findAlgorithm(exchange))
                 .setWithIntegrityPacket(integrity).setSecureRandom(new 
SecureRandom()).setProvider(getProvider()));
-        encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(key));
+        // several keys can be added
+        for (PGPPublicKey key : keys) {
+            encGen.addMethod(new 
JcePublicKeyKeyEncryptionMethodGenerator(key));
+        }
         OutputStream encOut = encGen.open(outputStream, new byte[BUFFER_SIZE]);
 
-        PGPCompressedDataGenerator comData = new 
PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP);
+        PGPCompressedDataGenerator comData = new 
PGPCompressedDataGenerator(findCompressionAlgorithm(exchange));
         OutputStream comOut = new BufferedOutputStream(comData.open(encOut));
 
         PGPSignatureGenerator sigGen = createSignatureGenerator(exchange, 
comOut);
@@ -244,6 +248,28 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         }
     }
 
+    public List<String> determineEncryptionUserIds(Exchange exchange) {
+        String userid = findKeyUserid(exchange);
+        List<String> userids = findKeyUserids(exchange);
+        // merge them together
+        List<String> result;
+        if (userid != null) {
+            if (userids == null || userids.isEmpty()) {
+                result = Collections.singletonList(userid);
+            } else {
+                result = new ArrayList<String>(userids.size() + 1);
+                result.add(userid);
+                result.addAll(userids);
+            }
+        } else {
+            if (userids == null || userids.isEmpty()) {
+                throw new IllegalStateException("Cannot PGP encrypt message. 
No User ID of the public key specified.");
+            }
+            result = userids;
+        }
+        return result;
+    }
+
     protected PGPSignatureGenerator createSignatureGenerator(Exchange 
exchange, OutputStream out) throws IOException, PGPException,
             NoSuchProviderException, NoSuchAlgorithmException {
 
@@ -259,12 +285,16 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         PGPSecretKey sigSecretKey = 
PGPDataFormatUtil.findSecretKey(exchange.getContext(), sigKeyFileName, 
sigKeyRing, sigKeyPassword,
                 sigKeyUserid, getProvider());
         if (sigSecretKey == null) {
-            throw new IllegalArgumentException("Signature secret key is null, 
cannot proceed");
+            throw new IllegalArgumentException(
+                    String.format(
+                            "Cannot PGP encrypt message. No secret key found 
for User ID %s. Either add a key with this User ID to the secret keyring or 
change the configured User ID.",
+                            sigKeyUserid));
         }
 
         PGPPrivateKey sigPrivateKey = sigSecretKey.extractPrivateKey(new 
JcePBESecretKeyDecryptorBuilder().setProvider(getProvider())
                 .build(sigKeyPassword.toCharArray()));
         if (sigPrivateKey == null) {
+            // this exception will never happen
             throw new IllegalArgumentException("Signature private key is null, 
cannot proceed");
         }
 
@@ -401,7 +431,8 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Sets if the encrypted file should be written in ascii visible text
+     * Sets if the encrypted file should be written in ascii visible text (for
+     * marshaling).
      */
     public void setArmored(boolean armored) {
         this.armored = armored;
@@ -412,7 +443,8 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Whether or not to add a integrity check/sign to the encrypted file
+     * Whether or not to add an integrity check/sign to the encrypted file for
+     * marshaling.
      */
     public void setIntegrity(boolean integrity) {
         this.integrity = integrity;
@@ -423,7 +455,11 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Userid of the key used to encrypt/decrypt
+     * Userid of the key used to encrypt. If you want to encrypt with several
+     * keys then use the method {@link #setKeyUserids(List<String>)}. The User
+     * ID of this method and the User IDs of the method {@link
+     * #setKeyUserids(List<String>)} will be merged together and the
+     * corresponding public keys will be used for the encryption.
      */
     public void setKeyUserid(String keyUserid) {
         this.keyUserid = keyUserid;
@@ -433,8 +469,25 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return keyUserid;
     }
 
+    public List<String> getKeyUserids() {
+        return keyUserids;
+    }
+
     /**
-     * filename of the keyring that will be used, classpathResource
+     * KeyUserIds used to determine the public keys for encryption. If you just
+     * have one User ID, then you can also use the method
+     * {@link #setKeyUserid(String)} or this method. The User ID specified in
+     * {@link #setKeyUserid(String)} and in this method will be merged together
+     * and the corresponding public keys will be used for the encryption.
+     */
+    public void setKeyUserids(List<String> keyUserids) {
+        this.keyUserids = keyUserids;
+    }
+
+    /**
+     * Filename of the keyring that will be used for the encryption/decryption,
+     * classpathResource. Alternatively you can provide the keyring also as 
byte
+     * array; see method {@link #setEncryptionKeyRing(byte[])}.
      */
     public void setKeyFileName(String keyFileName) {
         this.keyFileName = keyFileName;
@@ -445,7 +498,9 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Password used to open the private keyring
+     * Password used to open the private key in secret keyring for decryption
+     * (unmarshaling). See also
+     * {@link #setPassphraseAccessor(PGPPassphraseAccessor)}.
      */
     public void setPassword(String password) {
         this.password = password;
@@ -456,7 +511,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Userid of the signature key used to sign/verify
+     * Userid of the signature key used to sign (marshal).
      */
     public void setSignatureKeyUserid(String signatureKeyUserid) {
         this.signatureKeyUserid = signatureKeyUserid;
@@ -467,7 +522,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * filename of the signature keyring that will be used, classpathResource
+     * Filename of the signature keyring that will be used, classpathResource.
      */
     public void setSignatureKeyFileName(String signatureKeyFileName) {
         this.signatureKeyFileName = signatureKeyFileName;
@@ -478,7 +533,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Password used to open the signature private keyring
+     * Password used to open the signature private key during marshaling.
      */
     public void setSignaturePassword(String signaturePassword) {
         this.signaturePassword = signaturePassword;
@@ -492,6 +547,11 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return encryptionKeyRing;
     }
 
+    /**
+     * Keyring used for encryption/decryption as byte array. Alternatively you
+     * can also provide the keyring as a file; see method
+     * {@link #setKeyFileName(String)}.
+     */
     public void setEncryptionKeyRing(byte[] encryptionKeyRing) {
         this.encryptionKeyRing = encryptionKeyRing;
     }
@@ -500,6 +560,11 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return signatureKeyRing;
     }
 
+    /**
+     * Keyring used for signing/verifying as byte array. Alternatively you can
+     * also provide the keyring as a file; see method
+     * {@link #setSignatureKeyFileName(String)}.
+     */
     public void setSignatureKeyRing(byte[] signatureKeyRing) {
         this.signatureKeyRing = signatureKeyRing;
     }
@@ -508,14 +573,37 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return provider;
     }
 
+    /**
+     * Java Cryptography Extension (JCE) provider, default is Bouncy Castle
+     * ("BC"). Alternatively you can use, for example, the IAIK JCE provider; 
in
+     * this case the provider must be registered beforehand and the Bouncy
+     * Castle provider must not be registered beforehand. The Sun JCE provider
+     * does not work.
+     */
     public void setProvider(String provider) {
         this.provider = provider;
     }
 
+    public int getCompressionAlgorithm() {
+        return compressionAlgorithm;
+    }
+
+    /**
+     * Compression algorithm used during marshaling. Possible values are 
defined
+     * in {@link CompressionAlgorithmTags}. Default value is ZIP.
+     */
+    public void setCompressionAlgorithm(int compressionAlgorithm) {
+        this.compressionAlgorithm = compressionAlgorithm;
+    }
+
     public int getHashAlgorithm() {
         return hashAlgorithm;
     }
 
+    /**
+     * Digest algorithm for signing (marshaling). Possible values are defined 
in
+     * {@link HashAlgorithmTags}. Default value is SHA1.
+     */
     public void setHashAlgorithm(int hashAlgorithm) {
         this.hashAlgorithm = hashAlgorithm;
     }
@@ -524,6 +612,10 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return algorithm;
     }
 
+    /**
+     * Symmetric key algorithm for encryption (marshaling). Possible values are
+     * defined in {@link SymmetricKeyAlgorithmTags}. Default value is CAST5.
+     */
     public void setAlgorithm(int algorithm) {
         this.algorithm = algorithm;
     }
@@ -532,6 +624,15 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return passphraseAccessor;
     }
 
+    /**
+     * Alternative way to provide the passphrases. Especially useful for the
+     * unmarshal (decryption) case . If no passphrase can be found from the
+     * parameter <tt>password</tt> or <tt>signaturePassword</tt> or from the
+     * header {@link #SIGNATURE_KEY_PASSWORD} or {@link #KEY_PASSWORD} then we
+     * try to get the password from the passphrase accessor. This is especially
+     * useful in the decrypt case, where we chose the private key according to
+     * the key Id stored in the encrypted data.
+     */
     public void setPassphraseAccessor(PGPPassphraseAccessor 
passphraseAccessor) {
         this.passphraseAccessor = passphraseAccessor;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/5dd309b7/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 bff00ad..2ea229b 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
@@ -20,7 +20,10 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.NoSuchProviderException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.util.IOHelper;
@@ -56,17 +59,33 @@ public final class PGPDataFormatUtil {
         return findPublicKey(context, filename, null, userid, forEncryption);
     }
 
+    @Deprecated
     public static PGPPublicKey findPublicKey(CamelContext context, String 
filename, byte[] keyRing, String userid, boolean forEncryption)
         throws IOException, PGPException, NoSuchProviderException {
 
         InputStream is = determineKeyRingInputStream(context, filename, 
keyRing, forEncryption);
-        PGPPublicKey pubKey;
+
         try {
-            pubKey = findPublicKey(is, userid, forEncryption);
+            List<PGPPublicKey> result = findPublicKeys(is, 
Collections.singletonList(userid), forEncryption);
+            if (result.isEmpty()) {
+                return null;
+            } else {
+                return result.get(0);
+            }
+        } finally {
+            IOHelper.close(is);
+        }
+
+    }
+
+    public static List<PGPPublicKey> findPublicKeys(CamelContext context, 
String filename, byte[] keyRing, List<String> userids,
+            boolean forEncryption) throws IOException, PGPException, 
NoSuchProviderException {
+        InputStream is = determineKeyRingInputStream(context, filename, 
keyRing, forEncryption);
+        try {
+            return findPublicKeys(is, userids, forEncryption);
         } finally {
             IOHelper.close(is);
         }
-        return pubKey;
     }
 
     public static PGPPublicKey findPublicKeyWithKeyId(CamelContext context, 
String filename, byte[] keyRing, long keyid,
@@ -81,10 +100,10 @@ public final class PGPDataFormatUtil {
         return pubKey;
     }
 
-    public static PGPPrivateKey findPrivateKeyWithKeyId(CamelContext context, 
String filename, byte[] secreteKeyRing, long keyid,
+    public static PGPPrivateKey findPrivateKeyWithKeyId(CamelContext context, 
String filename, byte[] secretKeyRing, long keyid,
             String passphrase, PGPPassphraseAccessor passpraseAccessor, String 
provider) throws IOException, PGPException,
             NoSuchProviderException {
-        InputStream is = determineKeyRingInputStream(context, filename, 
secreteKeyRing, true);
+        InputStream is = determineKeyRingInputStream(context, filename, 
secretKeyRing, true);
         try {
             return findPrivateKeyWithKeyId(is, keyid, passphrase, 
passpraseAccessor, provider);
         } finally {
@@ -109,6 +128,9 @@ public final class PGPDataFormatUtil {
                             passphrase = 
passphraseAccessor.getPassphrase(userIDs.next());
                         }
                     }
+                    if (passphrase == null) {
+                        continue;
+                    }
                     PGPPrivateKey privateKey = secKey.extractPrivateKey(new 
JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(
                             passphrase.toCharArray()));
                     if (privateKey != null) {
@@ -160,32 +182,32 @@ public final class PGPDataFormatUtil {
     }
 
     @SuppressWarnings("unchecked")
-    private static PGPPublicKey findPublicKey(InputStream input, String 
userid, boolean forEncryption) throws IOException, PGPException,
-            NoSuchProviderException {
+    private static List<PGPPublicKey> findPublicKeys(InputStream input, 
List<String> userids, boolean forEncryption) throws IOException,
+            PGPException, NoSuchProviderException {
+        List<PGPPublicKey> result = new ArrayList<PGPPublicKey>(3);
+
         PGPPublicKeyRingCollection pgpSec = new 
PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input));
 
-        Iterator<PGPPublicKeyRing> keyRingIter = pgpSec.getKeyRings();
-        while (keyRingIter.hasNext()) {
+        for (Iterator<PGPPublicKeyRing> keyRingIter = pgpSec.getKeyRings(); 
keyRingIter.hasNext();) {
             PGPPublicKeyRing keyRing = keyRingIter.next();
-
-            Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys();
-            while (keyIter.hasNext()) {
+            for (Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys(); 
keyIter.hasNext();) {
                 PGPPublicKey key = keyIter.next();
                 for (Iterator<String> iterator = key.getUserIDs(); 
iterator.hasNext();) {
                     String keyUserId = iterator.next();
-                    // there can be serveral user IDs!
-                    if (keyUserId != null && keyUserId.contains(userid)) {
-                        if (forEncryption && key.isEncryptionKey()) {
-                            return key;
-                        } else if (!forEncryption && isSignatureKey(key)) {
-                            return key;
+                    for (String userid : userids) {
+                        if (keyUserId != null && keyUserId.contains(userid)) {
+                            if (forEncryption && key.isEncryptionKey()) {
+                                result.add(key);
+                            } else if (!forEncryption && isSignatureKey(key)) {
+                                result.add(key);
+                            }
                         }
                     }
                 }
             }
         }
 
-        return null;
+        return result;
     }
 
     private static boolean isSignatureKey(PGPPublicKey key) {

http://git-wip-us.apache.org/repos/asf/camel/blob/5dd309b7/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatDynamicTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatDynamicTest.java
 
b/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatDynamicTest.java
index af8d8c5..144b655 100644
--- 
a/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatDynamicTest.java
+++ 
b/components/camel-crypto/src/test/java/org/apache/camel/converter/crypto/PGPDataFormatDynamicTest.java
@@ -16,9 +16,13 @@
  */
 package org.apache.camel.converter.crypto;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.bouncycastle.bcpg.CompressionAlgorithmTags;
 import org.bouncycastle.bcpg.HashAlgorithmTags;
 import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
 
@@ -29,34 +33,50 @@ public class PGPDataFormatDynamicTest extends 
PGPDataFormatTest {
         return "wrong";
     }
 
+    // setup a wrong userids
+    @Override
+    protected List<String> getKeyUserIds() {
+        List<String> userids = new ArrayList<String>(2);
+        userids.add("wrong1");
+        userids.add(getKeyUserId());
+        return userids;
+    }
+
     // setup a wrong password
     @Override
     protected String getKeyPassword() {
         return "wrong";
     }
-    
-    
+
     //setup wrong algorithm
     @Override
     protected int getAlgorithm() {
         return -5;
     }
-    
+
     //setup wrong hash algorithm
+    @Override
     protected int getHashAlgorithm() {
         return -5;
     }
 
+    //setup wrong compression algorithm
+    @Override
+    protected int getCompressionAlgorithm() {
+        return -5;
+    }
 
     // override wrong userid and password with correct userid and password in 
the headers
     protected Map<String, Object> getHeaders() {
         Map<String, Object> headers = new HashMap<String, Object>();
         headers.put(PGPDataFormat.KEY_USERID, "sd...@nowhere.net");
+        headers.put(PGPDataFormat.KEY_USERIDS, 
Collections.singletonList("second"));
         headers.put(PGPDataFormat.SIGNATURE_KEY_USERID, "sd...@nowhere.net");
         headers.put(PGPDataFormat.KEY_PASSWORD, "sdude");
         headers.put(PGPDataFormat.SIGNATURE_KEY_PASSWORD, "sdude");
         headers.put(PGPDataFormat.ENCRYPTION_ALGORITHM, 
SymmetricKeyAlgorithmTags.AES_128);
         headers.put(PGPDataFormat.SIGNATURE_HASH_ALGORITHM, 
HashAlgorithmTags.SHA512);
+        headers.put(PGPDataFormat.COMPRESSION_ALGORITHM, 
CompressionAlgorithmTags.ZLIB);
         return headers;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/5dd309b7/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 20413c8..50af476 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
@@ -19,49 +19,62 @@ package org.apache.camel.converter.crypto;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.util.IOHelper;
+import org.bouncycastle.bcpg.CompressionAlgorithmTags;
 import org.bouncycastle.bcpg.HashAlgorithmTags;
 import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
 import org.junit.Test;
 
 public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
-    
+
     private static final String SEC_KEY_RING_FILE_NAME = 
"org/apache/camel/component/crypto/secring.gpg";
     private static final String PUB_KEY_RING_FILE_NAME = 
"org/apache/camel/component/crypto/pubring.gpg";
 
-    
     protected String getKeyFileName() {
         return PUB_KEY_RING_FILE_NAME;
     }
-    
+
     protected String getKeyFileNameSec() {
         return SEC_KEY_RING_FILE_NAME;
     }
-    
+
     protected String getKeyUserId() {
         return "sd...@nowhere.net";
     }
-    
+
+    protected List<String> getKeyUserIds() {
+        List<String> userids = new ArrayList<String>(2);
+        userids.add("second");
+        userids.add(getKeyUserId());
+        return userids;
+    }
+
     protected String getKeyPassword() {
         return "sdude";
     }
-    
+
     protected String getProvider() {
         return "BC";
     }
-    
+
     protected int getAlgorithm() {
         return SymmetricKeyAlgorithmTags.TRIPLE_DES;
     }
-    
+
     protected int getHashAlgorithm() {
         return HashAlgorithmTags.SHA256;
     }
 
+    protected int getCompressionAlgorithm() {
+        return CompressionAlgorithmTags.BZIP2;
+    }
+
     @Test
     public void testEncryption() throws Exception {
         doRoundTripEncryptionTests("direct:inline");
@@ -81,7 +94,7 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
     public void testEncryptionSigned() throws Exception {
         doRoundTripEncryptionTests("direct:inline-sign");
     }
-    
+
     @Test
     public void testEncryptionKeyRingByteArray() throws Exception {
         doRoundTripEncryptionTests("direct:key-ring-byte-array");
@@ -105,11 +118,8 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 // Private key password
                 String keyPassword = getKeyPassword();
 
-                from("direct:inline")
-                        .marshal().pgp(keyFileName, keyUserid)
-                        .to("mock:encrypted")
-                        .unmarshal().pgp(keyFileNameSec, null, keyPassword)
-                        .to("mock:unencrypted");
+                from("direct:inline").marshal().pgp(keyFileName, 
keyUserid).to("mock:encrypted").unmarshal()
+                        .pgp(keyFileNameSec, null, 
keyPassword).to("mock:unencrypted");
                 // END SNIPPET: pgp-format
 
                 // START SNIPPET: pgp-format-header
@@ -118,23 +128,17 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpEncrypt.setKeyUserid(keyUserid);
                 pgpEncrypt.setProvider(getProvider());
                 pgpEncrypt.setAlgorithm(getAlgorithm());
+                pgpEncrypt.setCompressionAlgorithm(getCompressionAlgorithm());
 
                 PGPDataFormat pgpDecrypt = new PGPDataFormat();
                 pgpDecrypt.setKeyFileName(keyFileNameSec);
                 pgpDecrypt.setPassword(keyPassword);
                 pgpDecrypt.setProvider(getProvider());
 
-                from("direct:inline2")
-                        .marshal(pgpEncrypt)
-                        .to("mock:encrypted")
-                        .unmarshal(pgpDecrypt)
-                        .to("mock:unencrypted");
+                
from("direct:inline2").marshal(pgpEncrypt).to("mock:encrypted").unmarshal(pgpDecrypt).to("mock:unencrypted");
 
-                from("direct:inline-armor")
-                        .marshal().pgp(keyFileName, keyUserid, null, true, 
true)
-                        .to("mock:encrypted")
-                        .unmarshal().pgp(keyFileNameSec, null, keyPassword, 
true, true)
-                        .to("mock:unencrypted");
+                from("direct:inline-armor").marshal().pgp(keyFileName, 
keyUserid, null, true, true).to("mock:encrypted").unmarshal()
+                        .pgp(keyFileNameSec, null, keyPassword, true, 
true).to("mock:unencrypted");
                 // END SNIPPET: pgp-format-header
 
                 // START SNIPPET: pgp-format-signature
@@ -148,7 +152,7 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpSignAndEncrypt.setProvider(getProvider());
                 pgpSignAndEncrypt.setAlgorithm(getAlgorithm());
                 pgpSignAndEncrypt.setHashAlgorithm(getHashAlgorithm());
-                
+                
pgpSignAndEncrypt.setCompressionAlgorithm(getCompressionAlgorithm());
 
                 PGPDataFormat pgpVerifyAndDecrypt = new PGPDataFormat();
                 pgpVerifyAndDecrypt.setKeyFileName(keyFileNameSec);
@@ -156,19 +160,17 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpVerifyAndDecrypt.setSignatureKeyFileName(keyFileName);
                 pgpVerifyAndDecrypt.setProvider(getProvider());
 
-                from("direct:inline-sign")
-                        .marshal(pgpSignAndEncrypt)
-                        .to("mock:encrypted")
-                        .unmarshal(pgpVerifyAndDecrypt)
+                
from("direct:inline-sign").marshal(pgpSignAndEncrypt).to("mock:encrypted").unmarshal(pgpVerifyAndDecrypt)
                         .to("mock:unencrypted");
                 // END SNIPPET: pgp-format-signature
                 /* ---- key ring as byte array -- */
                 // START SNIPPET: pgp-format-key-ring-byte-array
                 PGPDataFormat pgpEncryptByteArray = new PGPDataFormat();
                 pgpEncryptByteArray.setEncryptionKeyRing(getPublicKeyRing());
-                pgpEncryptByteArray.setKeyUserid(keyUserid);
+                pgpEncryptByteArray.setKeyUserids(getKeyUserIds());
                 pgpEncryptByteArray.setProvider(getProvider());
                 
pgpEncryptByteArray.setAlgorithm(SymmetricKeyAlgorithmTags.DES);
+                
pgpEncryptByteArray.setCompressionAlgorithm(CompressionAlgorithmTags.UNCOMPRESSED);
 
                 PGPDataFormat pgpDecryptByteArray = new PGPDataFormat();
                 pgpDecryptByteArray.setEncryptionKeyRing(getSecKeyRing());
@@ -188,6 +190,7 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpSignAndEncryptByteArray.setProvider(getProvider());
                 
pgpSignAndEncryptByteArray.setAlgorithm(SymmetricKeyAlgorithmTags.BLOWFISH);
                 
pgpSignAndEncryptByteArray.setHashAlgorithm(HashAlgorithmTags.RIPEMD160);
+                
pgpSignAndEncryptByteArray.setCompressionAlgorithm(CompressionAlgorithmTags.ZLIB);
 
                 PGPDataFormat pgpVerifyAndDecryptByteArray = new 
PGPDataFormat();
                 
pgpVerifyAndDecryptByteArray.setPassphraseAccessor(passphraseAccessor);
@@ -205,8 +208,6 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                         
.removeHeader(PGPDataFormat.SIGNATURE_KEY_RING).to("mock:unencrypted");
                 // END SNIPPET: pgp-format-signature-key-ring-byte-array
             }
-
-         
         };
     }
 
@@ -225,7 +226,7 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
         output.close();
         return output.toByteArray();
     }
-    
+
     public static PGPPassphraseAccessor getPassphraseAccessor() {
         Map<String, String> userId2Passphrase = 
Collections.singletonMap("Super <sd...@nowhere.net>", "sdude");
         PGPPassphraseAccessor passphraseAccessor = new 
PGPPassphraseAccessorDefault(userId2Passphrase);

http://git-wip-us.apache.org/repos/asf/camel/blob/5dd309b7/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/SpringPGPDataFormatTest.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/SpringPGPDataFormatTest.xml
 
b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/SpringPGPDataFormatTest.xml
index fcc15ac..6899fec 100644
--- 
a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/SpringPGPDataFormatTest.xml
+++ 
b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/SpringPGPDataFormatTest.xml
@@ -54,6 +54,7 @@
       <property name="keyUserid" value="sd...@nowhere.net"/>  
       <property name="encryptionKeyRing" ref="pubKeyRing"/>
       <property name="algorithm" value="7"/> <!-- AES128  algorithm -->
+      <property name="compressionAlgorithm" value="3"/> <!-- BZ2 compression 
-->
    </bean>
    
    <bean id="decryptBean" 
class="org.apache.camel.converter.crypto.PGPDataFormat"> 

Reply via email to