Updated Branches:
  refs/heads/camel-2.12.x 3a391332a -> f0e979e53

CAMEL-7002. Support for serveral signatures.


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

Branch: refs/heads/camel-2.12.x
Commit: f0e979e53344015dec3619a83053b4e4d20024a3
Parents: 3a39133
Author: Hadrian Zbarcea <[email protected]>
Authored: Fri Feb 7 15:36:01 2014 -0500
Committer: Hadrian Zbarcea <[email protected]>
Committed: Fri Feb 7 15:36:01 2014 -0500

----------------------------------------------------------------------
 .../camel/converter/crypto/PGPDataFormat.java   | 243 +++++++++++++++----
 .../converter/crypto/PGPDataFormatUtil.java     | 131 ++++++----
 .../crypto/PGPDataFormatDynamicTest.java        |  10 +
 .../converter/crypto/PGPDataFormatTest.java     | 149 +++++++++++-
 4 files changed, 438 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/f0e979e5/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 985e80d..0157088 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
@@ -29,9 +29,13 @@ import java.security.SignatureException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.camel.Exchange;
+import 
org.apache.camel.converter.crypto.PGPDataFormatUtil.PGPSecretKeyAndPrivateKeyAndUserId;
 import org.apache.camel.converter.stream.CachedOutputStream;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.support.ServiceSupport;
@@ -56,7 +60,6 @@ import org.bouncycastle.openpgp.PGPOnePassSignatureList;
 import org.bouncycastle.openpgp.PGPPrivateKey;
 import org.bouncycastle.openpgp.PGPPublicKey;
 import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
-import org.bouncycastle.openpgp.PGPSecretKey;
 import org.bouncycastle.openpgp.PGPSignature;
 import org.bouncycastle.openpgp.PGPSignatureGenerator;
 import org.bouncycastle.openpgp.PGPSignatureList;
@@ -64,7 +67,6 @@ import 
org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
 import org.bouncycastle.openpgp.PGPUtil;
 import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
 import 
org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
-import 
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
 import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
 import 
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
 import 
org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
@@ -86,6 +88,7 @@ public class PGPDataFormat extends ServiceSupport implements 
DataFormat {
     public static final String SIGNATURE_KEY_FILE_NAME = 
"CamelPGPDataFormatSignatureKeyFileName";
     public static final String SIGNATURE_KEY_RING = 
"CamelPGPDataFormatSignatureKeyRing";
     public static final String SIGNATURE_KEY_USERID = 
"CamelPGPDataFormatSignatureKeyUserid";
+    public static final String SIGNATURE_KEY_USERIDS = 
"CamelPGPDataFormatSignatureKeyUserids";
     public static final String SIGNATURE_KEY_PASSWORD = 
"CamelPGPDataFormatSignatureKeyPassword";
     public static final String ENCRYPTION_ALGORITHM = 
"CamelPGPDataFormatEncryptionAlgorithm";
     public static final String SIGNATURE_HASH_ALGORITHM = 
"CamelPGPDataFormatSignatureHashAlgorithm";
@@ -109,8 +112,10 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     private byte[] encryptionKeyRing;
 
     // signature / verification key info (optional)
-    private String signatureKeyUserid; // for encryption
-    private String signaturePassword; // for encryption
+    private String signatureKeyUserid; // for signing and verification 
(optional for verification)
+    //For verification you can specify further User IDs in addition
+    private List<String> signatureKeyUserids; //only for signing with several 
keys and verifying;
+    private String signaturePassword; //only for signing, optional if you have 
several signature keys, then you should use passphaseAccessor
     private String signatureKeyFileName;
     // alternatively to the signature key file name you can specify the 
signature key ring as byte array
     private byte[] signatureKeyRing;
@@ -124,7 +129,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
 
     private int compressionAlgorithm = CompressionAlgorithmTags.ZIP; // for 
encryption
 
-    private PGPPassphraseAccessor passphraseAccessor;
+    private PGPPassphraseAccessor passphraseAccessor; // for signing and 
decryption with multiple keys
 
     public PGPDataFormat() {
     }
@@ -168,6 +173,11 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return exchange.getIn().getHeader(SIGNATURE_KEY_USERID, 
getSignatureKeyUserid(), String.class);
     }
 
+    @SuppressWarnings("unchecked")
+    protected List<String> findSignatureKeyUserids(Exchange exchange) {
+        return exchange.getIn().getHeader(SIGNATURE_KEY_USERIDS, 
getSignatureKeyUserids(), List.class);
+    }
+
     protected String findSignatureKeyPassword(Exchange exchange) {
         String sigPassword = 
exchange.getIn().getHeader(SIGNATURE_KEY_PASSWORD, getSignaturePassword(), 
String.class);
         if (sigPassword != null) {
@@ -218,7 +228,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         PGPCompressedDataGenerator comData = new 
PGPCompressedDataGenerator(findCompressionAlgorithm(exchange));
         OutputStream comOut = new BufferedOutputStream(comData.open(encOut));
 
-        PGPSignatureGenerator sigGen = createSignatureGenerator(exchange, 
comOut);
+        List<PGPSignatureGenerator> sigGens = 
createSignatureGenerator(exchange, comOut);
 
         PGPLiteralDataGenerator litData = new PGPLiteralDataGenerator();
         String fileName = exchange.getIn().getHeader(Exchange.FILE_NAME, 
String.class);
@@ -234,21 +244,29 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
             int bytesRead;
             while ((bytesRead = input.read(buffer)) != -1) {
                 litOut.write(buffer, 0, bytesRead);
-                if (sigGen != null) {
-                    sigGen.update(buffer, 0, bytesRead);
+                if (sigGens != null && !sigGens.isEmpty()) {
+                    for (PGPSignatureGenerator sigGen : sigGens) {
+                        // not nested therefore it is the same for all
+                        // can this be improved that we only do it for one 
sigGen and set the result on the others?
+                        sigGen.update(buffer, 0, bytesRead);
+                    }
                 }
                 litOut.flush();
             }
         } finally {
             IOHelper.close(litOut);
-            if (sigGen != null) {
-                sigGen.generate().encode(comOut);
+            if (sigGens != null && !sigGens.isEmpty()) {
+                // reverse order
+                for (int i = sigGens.size() - 1; i > -1; i--) {
+                    PGPSignatureGenerator sigGen = sigGens.get(i);
+                    sigGen.generate().encode(comOut);
+                }
             }
             IOHelper.close(comOut, encOut, outputStream, input);
         }
     }
 
-    public List<String> determineEncryptionUserIds(Exchange exchange) {
+    protected List<String> determineEncryptionUserIds(Exchange exchange) {
         String userid = findKeyUserid(exchange);
         List<String> userids = findKeyUserids(exchange);
         // merge them together
@@ -270,44 +288,94 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return result;
     }
 
-    protected PGPSignatureGenerator createSignatureGenerator(Exchange 
exchange, OutputStream out) throws IOException, PGPException,
+    protected List<String> determineSignaturenUserIds(Exchange exchange) {
+        String userid = findSignatureKeyUserid(exchange);
+        List<String> userids = findSignatureKeyUserids(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 {
+            // userids can be empty or null!
+            result = userids;
+        }
+        return result;
+    }
+
+    protected List<PGPSignatureGenerator> createSignatureGenerator(Exchange 
exchange, OutputStream out) throws IOException, PGPException,
             NoSuchProviderException, NoSuchAlgorithmException {
 
         String sigKeyFileName = findSignatureKeyFileName(exchange);
-        String sigKeyUserid = findSignatureKeyUserid(exchange);
+        List<String> sigKeyUserids = determineSignaturenUserIds(exchange);
         String sigKeyPassword = findSignatureKeyPassword(exchange);
         byte[] sigKeyRing = findSignatureKeyRing(exchange);
 
-        if ((sigKeyFileName == null && sigKeyRing == null) || sigKeyUserid == 
null || sigKeyPassword == null) {
+        if ((sigKeyFileName == null && sigKeyRing == null) || sigKeyUserids == 
null || sigKeyUserids.isEmpty()
+                || (sigKeyPassword == null && passphraseAccessor == null)) {
             return null;
         }
 
-        PGPSecretKey sigSecretKey = 
PGPDataFormatUtil.findSecretKey(exchange.getContext(), sigKeyFileName, 
sigKeyRing, sigKeyPassword,
-                sigKeyUserid, getProvider());
-        if (sigSecretKey == null) {
+        List<PGPSecretKeyAndPrivateKeyAndUserId> 
sigSecretKeysWithPrivateKeyAndUserId = 
determineSecretKeysWithPrivateKeyAndUserId(
+                exchange, sigKeyFileName, sigKeyUserids, sigKeyPassword, 
sigKeyRing);
+
+        List<PGPSignatureGenerator> sigGens = new 
ArrayList<PGPSignatureGenerator>();
+        for (PGPSecretKeyAndPrivateKeyAndUserId 
sigSecretKeyWithPrivateKeyAndUserId : sigSecretKeysWithPrivateKeyAndUserId) {
+            PGPPrivateKey sigPrivateKey = 
sigSecretKeyWithPrivateKeyAndUserId.getPrivateKey();
+
+            PGPSignatureSubpacketGenerator spGen = new 
PGPSignatureSubpacketGenerator();
+            spGen.setSignerUserID(false, 
sigSecretKeyWithPrivateKeyAndUserId.getUserId());
+
+            int algorithm = 
sigSecretKeyWithPrivateKeyAndUserId.getSecretKey().getPublicKey().getAlgorithm();
+            PGPSignatureGenerator sigGen = new PGPSignatureGenerator(
+                    new JcaPGPContentSignerBuilder(algorithm, 
findHashAlgorithm(exchange)).setProvider(getProvider()));
+            sigGen.init(PGPSignature.BINARY_DOCUMENT, sigPrivateKey);
+            sigGen.setHashedSubpackets(spGen.generate());
+            sigGen.generateOnePassVersion(false).encode(out);
+            sigGens.add(sigGen);
+        }
+        return sigGens;
+    }
+
+    public List<PGPSecretKeyAndPrivateKeyAndUserId> 
determineSecretKeysWithPrivateKeyAndUserId(Exchange exchange, String 
sigKeyFileName,
+            List<String> sigKeyUserids, String sigKeyPassword, byte[] 
sigKeyRing) throws IOException, PGPException, NoSuchProviderException {
+
+        Map<String, String> sigKeyUserId2Password = 
determineSignatureKeyUserId2Password(sigKeyUserids, sigKeyPassword);
+
+        List<PGPSecretKeyAndPrivateKeyAndUserId> 
sigSecretKeysWithPrivateKeyAndUserId = PGPDataFormatUtil
+                .findSecretKeysWithPrivateKeyAndUserId(exchange.getContext(), 
sigKeyFileName, sigKeyRing, sigKeyUserId2Password,
+                        getProvider());
+
+        if (sigSecretKeysWithPrivateKeyAndUserId.isEmpty()) {
             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));
+                            "Cannot PGP sign message. No secret key found for 
User IDs %s. Either add keys with this User IDs to the secret keyring or change 
the configured User IDs.",
+                            sigKeyUserids));
         }
+        return sigSecretKeysWithPrivateKeyAndUserId;
+    }
 
-        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");
+    public Map<String, String> 
determineSignatureKeyUserId2Password(List<String> sigKeyUserids, String 
sigKeyPassword) {
+        // we want to keep the order of the entries, therefore we use 
LinkedHashMap
+        Map<String, String> sigKeyUserId2Password = new LinkedHashMap<String, 
String>(sigKeyUserids.size());
+        for (String sigKeyUserid : sigKeyUserids) {
+            if (sigKeyPassword == null) {
+                sigKeyPassword = 
passphraseAccessor.getPassphrase(sigKeyUserid);
+            }
+            if (sigKeyPassword == null) {
+                throw new IllegalArgumentException(
+                        String.format(
+                                "No passphrase specified for signature key 
user ID %s. Either specify a passphrase or remove this user ID from the 
configuration.",
+                                sigKeyUserid));
+            }
+            sigKeyUserId2Password.put(sigKeyUserid, sigKeyPassword);
         }
-
-        PGPSignatureSubpacketGenerator spGen = new 
PGPSignatureSubpacketGenerator();
-        spGen.setSignerUserID(false, sigKeyUserid);
-
-        int algorithm = sigSecretKey.getPublicKey().getAlgorithm();
-        PGPSignatureGenerator sigGen = new PGPSignatureGenerator(
-                new JcaPGPContentSignerBuilder(algorithm, 
findHashAlgorithm(exchange)).setProvider(getProvider()));
-        sigGen.init(PGPSignature.BINARY_DOCUMENT, sigPrivateKey);
-        sigGen.setHashedSubpackets(spGen.generate());
-        sigGen.generateOnePassVersion(false).encode(out);
-        return sigGen;
+        return sigKeyUserId2Password;
     }
 
     @SuppressWarnings("resource")
@@ -333,6 +401,10 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
             pbe = (PGPPublicKeyEncryptedData) enc.get(i);
             key = 
PGPDataFormatUtil.findPrivateKeyWithKeyId(exchange.getContext(), 
findKeyFileName(exchange),
                     findEncryptionKeyRing(exchange), pbe.getKeyID(), 
findKeyPassword(exchange), getPassphraseAccessor(), getProvider());
+            if (key != null) {
+                // take the first key
+                break;
+            }
         }
         if (key == null) {
             throw new PGPException("Provided input is encrypted with unknown 
pair of keys.");
@@ -368,7 +440,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
             bos = new ByteArrayOutputStream();
             os = bos;
         }
-         
+
         try {
             byte[] buffer = new byte[BUFFER_SIZE];
             int bytesRead;
@@ -389,7 +461,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
                 throw new SignatureException("Cannot verify PGP signature");
             }
         }
-        
+
         if (cos != null) {
             return cos.newStreamCache();
         } else {
@@ -410,6 +482,7 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     protected PGPOnePassSignature getSignature(Exchange exchange, 
PGPOnePassSignatureList signatureList) throws IOException, PGPException,
             NoSuchProviderException {
 
+        List<String> allowedUserIds = determineSignaturenUserIds(exchange);
         for (int i = 0; i < signatureList.size(); i++) {
             PGPOnePassSignature signature = signatureList.get(i);
             // Determine public key from signature keyId
@@ -418,9 +491,11 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
             if (sigPublicKey == null) {
                 continue;
             }
-            // choose that signature for which a public key exists!
-            signature.init(new 
JcaPGPContentVerifierBuilderProvider().setProvider(getProvider()), 
sigPublicKey);
-            return signature;
+            if (isAllowedVerifyingKey(allowedUserIds, sigPublicKey)) {
+                // choose that signature for which a public key exists!
+                signature.init(new 
JcaPGPContentVerifierBuilderProvider().setProvider(getProvider()), 
sigPublicKey);
+                return signature;
+            }
         }
         if (signatureList.isEmpty()) {
             return null;
@@ -430,6 +505,31 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
 
     }
 
+    public boolean isAllowedVerifyingKey(List<String> allowedUserIds, 
PGPPublicKey verifyingPublicKey) {
+
+        if (allowedUserIds == null || allowedUserIds.isEmpty()) {
+            // no restrictions specified
+            return true;
+        }
+        String keyUserId = null;
+        for (@SuppressWarnings("unchecked")
+        Iterator<String> iterator = verifyingPublicKey.getUserIDs(); 
iterator.hasNext();) {
+            keyUserId = iterator.next();
+            for (String userid : allowedUserIds) {
+                if (keyUserId != null && keyUserId.contains(userid)) {
+                    LOG.debug(
+                            "Public key with  user ID {} fulfills the User ID 
restriction {}. Therefore this key will be used for the signature verification. 
",
+                            keyUserId, allowedUserIds);
+                    return true;
+                }
+            }
+        }
+        LOG.warn(
+                "Public key with User ID {} does not fulfill the User ID 
restriction {}. Therefore this key will not be used for the signature 
verification.",
+                keyUserId, allowedUserIds);
+        return false;
+    }
+
     /**
      * Sets if the encrypted file should be written in ascii visible text (for
      * marshaling).
@@ -455,11 +555,8 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * 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.
+     * User ID, or more precisely user ID part, of the key used for encryption.
+     * See also {@link #setKeyUserids(List<String>)}.
      */
     public void setKeyUserid(String keyUserid) {
         this.keyUserid = keyUserid;
@@ -474,11 +571,15 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * 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.
+     * Keys User IDs, or more precisely user ID parts, used for determining the
+     * public keys for encryption. If you just have one User ID, then you can
+     * also use the method {@link #setKeyUserid(String)}. The User ID specified
+     * in {@link #setKeyUserid(String)} and in this method will be merged
+     * together and the public keys which have a User ID which contain a value
+     * of the specified User IDs the will be used for the encryption. Be aware
+     * that you may get several public keys even if you specify only one User
+     * Id, because there can be several public keys which have a User ID which
+     * contains the specified User ID.
      */
     public void setKeyUserids(List<String> keyUserids) {
         this.keyUserids = keyUserids;
@@ -511,7 +612,9 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
     }
 
     /**
-     * Userid of the signature key used to sign (marshal).
+     * Userid, or more precisely user ID part, of the signature key used for
+     * signing (marshal) and verifying (unmarshal). See also
+     * {@link #setSignatureKeyUserids(List)}.
      */
     public void setSignatureKeyUserid(String signatureKeyUserid) {
         this.signatureKeyUserid = signatureKeyUserid;
@@ -521,6 +624,44 @@ public class PGPDataFormat extends ServiceSupport 
implements DataFormat {
         return signatureKeyUserid;
     }
 
+    public List<String> getSignatureKeyUserids() {
+        return signatureKeyUserids;
+    }
+
+    /**
+     * User IDs, or more precisely user ID parts, used for signing and
+     * verification.
+     * <p>
+     * In the signing case, the User IDs specify the private keys which are 
used
+     * for signing. If the result are several private keys then several
+     * signatures will be created. If you just have one signature User ID, then
+     * you can also use the method {@link #setSignatureKeyUserid(String)} or
+     * this method. The User ID specified in
+     * {@link #setSignatureKeyUserid(String)} and in this method will be merged
+     * together and the private keys which have a User Id which contain one
+     * value out of the specified UserIds will be used for the signature
+     * creation. Be aware that you may get several private keys even if you
+     * specify only one User Id, because there can be several private keys 
which
+     * have a User ID which contains the specified User ID.
+     * <p>
+     * In the verification case the User IDs restrict the set of public keys
+     * which can be used for verification. The public keys used for 
verification
+     * must contain a User ID which contain one value of the User ID list. If
+     * you neither specify in this method and nor specify in the method
+     * {@link #setSignatureKeyUserid(String)} any value then any public key in
+     * the public key ring will be taken into consideration for the
+     * verification.
+     * <p>
+     * If you just have one User ID, then you can also use the method
+     * {@link #setSignatureKeyUserid(String)}. The User ID specified in
+     * {@link #setSignatureKeyUserid(String)} and in this method will be merged
+     * together and the corresponding public keys represent the potential keys
+     * for the verification of the message.
+     */
+    public void setSignatureKeyUserids(List<String> signatureKeyUserids) {
+        this.signatureKeyUserids = signatureKeyUserids;
+    }
+
     /**
      * Filename of the signature keyring that will be used, classpathResource.
      */

http://git-wip-us.apache.org/repos/asf/camel/blob/f0e979e5/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 0753957..3408a4a 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
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
@@ -43,6 +44,8 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
 import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
 import org.bouncycastle.openpgp.PGPUtil;
 import 
org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.DSA;
 import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.ECDSA;
@@ -51,6 +54,8 @@ import static 
org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_GENERAL;
 import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_SIGN;
 
 public final class PGPDataFormatUtil {
+    
+    private static final Logger LOG = 
LoggerFactory.getLogger(PGPDataFormatUtil.class);
 
     private PGPDataFormatUtil() {
     }
@@ -81,7 +86,7 @@ public final class PGPDataFormatUtil {
     }
 
     public static List<PGPPublicKey> findPublicKeys(CamelContext context, 
String filename, byte[] keyRing, List<String> userids,
-            boolean forEncryption) throws IOException, PGPException, 
NoSuchProviderException {
+        boolean forEncryption) throws IOException, PGPException, 
NoSuchProviderException {
         InputStream is = determineKeyRingInputStream(context, filename, 
keyRing, forEncryption);
         try {
             return findPublicKeys(is, userids, forEncryption);
@@ -91,7 +96,7 @@ public final class PGPDataFormatUtil {
     }
 
     public static PGPPublicKey findPublicKeyWithKeyId(CamelContext context, 
String filename, byte[] keyRing, long keyid,
-            boolean forEncryption) throws IOException, PGPException, 
NoSuchProviderException {
+        boolean forEncryption) throws IOException, PGPException, 
NoSuchProviderException {
         InputStream is = determineKeyRingInputStream(context, filename, 
keyRing, forEncryption);
         PGPPublicKey pubKey;
         try {
@@ -103,8 +108,8 @@ public final class PGPDataFormatUtil {
     }
 
     public static PGPPrivateKey findPrivateKeyWithKeyId(CamelContext context, 
String filename, byte[] secretKeyRing, long keyid,
-            String passphrase, PGPPassphraseAccessor passpraseAccessor, String 
provider) throws IOException, PGPException,
-            NoSuchProviderException {
+        String passphrase, PGPPassphraseAccessor passpraseAccessor, String 
provider) throws IOException, PGPException,
+        NoSuchProviderException {
         InputStream is = determineKeyRingInputStream(context, filename, 
secretKeyRing, true);
         try {
             return findPrivateKeyWithKeyId(is, keyid, passphrase, 
passpraseAccessor, provider);
@@ -115,7 +120,7 @@ public final class PGPDataFormatUtil {
 
     @SuppressWarnings("unchecked")
     private static PGPPrivateKey findPrivateKeyWithKeyId(InputStream 
keyringInput, long keyid, String passphrase,
-            PGPPassphraseAccessor passphraseAccessor, String provider) throws 
IOException, PGPException {
+        PGPPassphraseAccessor passphraseAccessor, String provider) throws 
IOException, PGPException {
         PGPSecretKeyRingCollection pgpSec = new 
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput));
         for (Iterator<?> i = pgpSec.getKeyRings(); i.hasNext();) {
             Object data = i.next();
@@ -168,25 +173,24 @@ public final class PGPDataFormatUtil {
 
     @SuppressWarnings("unchecked")
     private static PGPPublicKey findPublicKeyWithKeyId(InputStream input, long 
keyid) throws IOException, PGPException,
-            NoSuchProviderException {
+        NoSuchProviderException {
         PGPPublicKeyRingCollection pgpSec = new 
PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input));
 
         for (Iterator<PGPPublicKeyRing> keyRingIter = pgpSec.getKeyRings(); 
keyRingIter.hasNext();) {
-            PGPPublicKeyRing keyRing = keyRingIter.next();
-            for (Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys(); 
keyIter.hasNext();) {
-                PGPPublicKey key = keyIter.next();
-                if (keyid == key.getKeyID()) {
-                    return key;
-                }
+            PGPPublicKeyRing keyRing = keyRingIter.next();           
+            PGPPublicKey key = keyRing.getPublicKey(keyid);
+            if (key != null) {
+                return key;
             }
-        }
 
+        }
+        
         return null;
     }
 
     @SuppressWarnings("unchecked")
     private static List<PGPPublicKey> findPublicKeys(InputStream input, 
List<String> userids, boolean forEncryption) throws IOException,
-            PGPException, NoSuchProviderException {
+        PGPException, NoSuchProviderException {
         List<PGPPublicKey> result = new ArrayList<PGPPublicKey>(3);
 
         PGPPublicKeyRingCollection pgpSec = new 
PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input));
@@ -196,13 +200,17 @@ public final class PGPDataFormatUtil {
             Set<String> keyUserIds = getUserIds(keyRing);
             for (Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys(); 
keyIter.hasNext();) {
                 PGPPublicKey key = keyIter.next();
-                for (String userid : userids) {
+                for (String useridPart : userids) {
                     for (String keyUserId : keyUserIds) {
-                        if (keyUserId != null && keyUserId.contains(userid)) {
+                        if (keyUserId != null && 
keyUserId.contains(useridPart)) {
                             if (forEncryption && key.isEncryptionKey()) {
                                 result.add(key);
+                                LOG.debug("Public key with key user ID {} and 
key ID {} found for specified user ID part {}", new Object[] {
+                                    keyUserId, Long.toString(key.getKeyID()), 
useridPart });
                             } else if (!forEncryption && isSignatureKey(key)) {
                                 result.add(key);
+                                LOG.debug("Public key with key user ID {} and 
key ID {} found for specified user ID part {}", new Object[] {
+                                    keyUserId, Long.toString(key.getKeyID()), 
useridPart });
                             }
                         }
                     }
@@ -243,14 +251,14 @@ public final class PGPDataFormatUtil {
 
     @Deprecated
     public static PGPPrivateKey findPrivateKey(CamelContext context, String 
keychainFilename, byte[] secKeyRing,
-            InputStream encryptedInput, String passphrase, String provider) 
throws IOException, PGPException, NoSuchProviderException {
+        InputStream encryptedInput, String passphrase, String provider) throws 
IOException, PGPException, NoSuchProviderException {
         return findPrivateKey(context, keychainFilename, secKeyRing, 
encryptedInput, passphrase, null, provider);
     }
 
     @Deprecated
     public static PGPPrivateKey findPrivateKey(CamelContext context, String 
keychainFilename, byte[] secKeyRing,
-            InputStream encryptedInput, String passphrase, 
PGPPassphraseAccessor passphraseAccessor, String provider) throws IOException,
-            PGPException, NoSuchProviderException {
+        InputStream encryptedInput, String passphrase, PGPPassphraseAccessor 
passphraseAccessor, String provider) throws IOException,
+        PGPException, NoSuchProviderException {
 
         InputStream keyChainInputStream = determineKeyRingInputStream(context, 
keychainFilename, secKeyRing, true);
         PGPPrivateKey privKey = null;
@@ -264,7 +272,7 @@ public final class PGPDataFormatUtil {
 
     @Deprecated
     private static PGPPrivateKey findPrivateKey(InputStream keyringInput, 
InputStream encryptedInput, String passphrase,
-            PGPPassphraseAccessor passphraseAccessor, String provider) throws 
IOException, PGPException, NoSuchProviderException {
+        PGPPassphraseAccessor passphraseAccessor, String provider) throws 
IOException, PGPException, NoSuchProviderException {
         PGPSecretKeyRingCollection pgpSec = new 
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput));
         PGPObjectFactory factory = new 
PGPObjectFactory(PGPUtil.getDecoderStream(encryptedInput));
         PGPEncryptedDataList enc;
@@ -305,60 +313,101 @@ public final class PGPDataFormatUtil {
 
     @Deprecated
     public static PGPSecretKey findSecretKey(CamelContext context, String 
keychainFilename, String passphrase) throws IOException,
-            PGPException, NoSuchProviderException {
+        PGPException, NoSuchProviderException {
         return findSecretKey(context, keychainFilename, null, passphrase, 
"BC");
     }
 
+    @Deprecated
     public static PGPSecretKey findSecretKey(CamelContext context, String 
keychainFilename, byte[] secKeyRing, String passphrase,
-            String userId, String provider) throws IOException, PGPException, 
NoSuchProviderException {
+        String userId, String provider) throws IOException, PGPException, 
NoSuchProviderException {
         InputStream keyChainInputStream = determineKeyRingInputStream(context, 
keychainFilename, secKeyRing, false);
-        PGPSecretKey secKey = null;
         try {
-            secKey = findSecretKey(keyChainInputStream, passphrase, userId, 
provider);
+            List<PGPSecretKeyAndPrivateKeyAndUserId> secKeys = 
findSecretKeysWithPrivateKeyAndUserId(keyChainInputStream,
+                    Collections.singletonMap(userId, passphrase), provider);
+            if (!secKeys.isEmpty()) {
+                return secKeys.get(0).getSecretKey();
+            }
+            return null;
+        } finally {
+            IOHelper.close(keyChainInputStream);
+        }
+    }
+
+    public static List<PGPSecretKeyAndPrivateKeyAndUserId> 
findSecretKeysWithPrivateKeyAndUserId(CamelContext context,
+        String keychainFilename, byte[] secKeyRing, Map<String, String> 
sigKeyUserId2Password, String provider) throws IOException,
+        PGPException, NoSuchProviderException {
+        InputStream keyChainInputStream = determineKeyRingInputStream(context, 
keychainFilename, secKeyRing, false);
+        try {
+            return findSecretKeysWithPrivateKeyAndUserId(keyChainInputStream, 
sigKeyUserId2Password, provider);
         } finally {
             IOHelper.close(keyChainInputStream);
         }
-        return secKey;
     }
 
     @Deprecated
     public static PGPSecretKey findSecretKey(CamelContext context, String 
keychainFilename, byte[] secKeyRing, String passphrase,
-            String provider) throws IOException, PGPException, 
NoSuchProviderException {
+        String provider) throws IOException, PGPException, 
NoSuchProviderException {
 
         return findSecretKey(context, keychainFilename, secKeyRing, 
passphrase, null, provider);
     }
 
     @SuppressWarnings("unchecked")
-    private static PGPSecretKey findSecretKey(InputStream keyringInput, String 
passphrase, String userId, String provider)
-        throws IOException, PGPException, NoSuchProviderException {
-        PGPSecretKey pgpSecKey = null;
+    private static List<PGPSecretKeyAndPrivateKeyAndUserId> 
findSecretKeysWithPrivateKeyAndUserId(InputStream keyringInput,
+        Map<String, String> sigKeyUserId2Password, String provider) throws 
IOException, PGPException, NoSuchProviderException {
+        List<PGPSecretKeyAndPrivateKeyAndUserId> result = new 
ArrayList<PGPDataFormatUtil.PGPSecretKeyAndPrivateKeyAndUserId>(
+                sigKeyUserId2Password.size());
         PGPSecretKeyRingCollection pgpSec = new 
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput));
-        for (Iterator<?> i = pgpSec.getKeyRings(); i.hasNext() && pgpSecKey == 
null;) {
+        for (Iterator<?> i = pgpSec.getKeyRings(); i.hasNext();) {
             Object data = i.next();
             if (data instanceof PGPSecretKeyRing) {
                 PGPSecretKeyRing keyring = (PGPSecretKeyRing) data;
                 PGPSecretKey secKey = keyring.getSecretKey();
-                if (userId != null) {
+                for (String userIdPart : sigKeyUserId2Password.keySet()) {
                     for (Iterator<String> iterator = secKey.getUserIDs(); 
iterator.hasNext();) {
                         String keyUserId = iterator.next();
                         // there can be serveral user IDs!
-                        if (keyUserId != null && keyUserId.contains(userId)) {
+                        if (keyUserId != null && 
keyUserId.contains(userIdPart)) {
                             PGPPrivateKey privateKey = 
secKey.extractPrivateKey(new 
JcePBESecretKeyDecryptorBuilder().setProvider(provider)
-                                    .build(passphrase.toCharArray()));
+                                    
.build(sigKeyUserId2Password.get(userIdPart).toCharArray()));
                             if (privateKey != null) {
-                                return secKey;
+                                result.add(new 
PGPSecretKeyAndPrivateKeyAndUserId(secKey, privateKey, keyUserId));
+                                LOG.debug("Private key with key user ID {} and 
key ID {} found for specified user ID part {}",
+                                        new Object[] {keyUserId, 
Long.toString(privateKey.getKeyID()), userIdPart});
+
                             }
                         }
                     }
-                } else {
-                    PGPPrivateKey privateKey = secKey.extractPrivateKey(new 
JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(
-                            passphrase.toCharArray()));
-                    if (privateKey != null) {
-                        pgpSecKey = secKey;
-                    }
                 }
             }
         }
-        return pgpSecKey;
+        return result;
+    }
+
+    public static class PGPSecretKeyAndPrivateKeyAndUserId {
+
+        private final PGPSecretKey secretKey;
+
+        private final PGPPrivateKey privateKey;
+
+        private final String userId;
+
+        public PGPSecretKeyAndPrivateKeyAndUserId(PGPSecretKey secretKey, 
PGPPrivateKey privateKey, String userId) {
+            this.secretKey = secretKey;
+            this.privateKey = privateKey;
+            this.userId = userId;
+        }
+
+        public PGPSecretKey getSecretKey() {
+            return secretKey;
+        }
+
+        public PGPPrivateKey getPrivateKey() {
+            return privateKey;
+        }
+
+        public String getUserId() {
+            return userId;
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f0e979e5/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 144b655..6250695 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
@@ -41,6 +41,15 @@ public class PGPDataFormatDynamicTest extends 
PGPDataFormatTest {
         userids.add(getKeyUserId());
         return userids;
     }
+    
+    // setup a wrong signature userids
+    @Override
+    protected List<String> getSignatureKeyUserIds() {
+        List<String> userids = new ArrayList<String>(2);
+        userids.add("wrong1");
+        userids.add(getKeyUserId());
+        return userids;
+    }
 
     // setup a wrong password
     @Override
@@ -77,6 +86,7 @@ public class PGPDataFormatDynamicTest extends 
PGPDataFormatTest {
         headers.put(PGPDataFormat.ENCRYPTION_ALGORITHM, 
SymmetricKeyAlgorithmTags.AES_128);
         headers.put(PGPDataFormat.SIGNATURE_HASH_ALGORITHM, 
HashAlgorithmTags.SHA512);
         headers.put(PGPDataFormat.COMPRESSION_ALGORITHM, 
CompressionAlgorithmTags.ZLIB);
+        headers.put(PGPDataFormat.SIGNATURE_KEY_USERIDS, 
Collections.singletonList("second"));
         return headers;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f0e979e5/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 50af476..b815882 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
@@ -20,11 +20,15 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.util.IOHelper;
 import org.bouncycastle.bcpg.CompressionAlgorithmTags;
 import org.bouncycastle.bcpg.HashAlgorithmTags;
@@ -55,6 +59,13 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
         return userids;
     }
 
+    protected List<String> getSignatureKeyUserIds() {
+        List<String> userids = new ArrayList<String>(2);
+        userids.add("second");
+        userids.add(getKeyUserId());
+        return userids;
+    }
+
     protected String getKeyPassword() {
         return "sdude";
     }
@@ -105,9 +116,62 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
         doRoundTripEncryptionTests("direct:sign-key-ring-byte-array");
     }
 
+    @Test
+    public void testSeveralSignerKeys() throws Exception {
+        doRoundTripEncryptionTests("direct:several-signer-keys");
+    }
+    
+    @Test
+    public void testOneUserIdWithServeralKeys() throws Exception {
+        doRoundTripEncryptionTests("direct:one-userid-several-keys");
+    }
+
+    @Test
+    public void 
testVerifyExceptionNoPublicKeyFoundCorrespondingToSignatureUserIds() throws 
Exception {
+        setupExpectations(context, 1, "mock:encrypted");
+        MockEndpoint exception = setupExpectations(context, 1, 
"mock:exception");
+
+        String payload = "Hi Alice, Be careful Eve is listening, signed Bob";
+        Map<String, Object> headers = getHeaders();
+        template.sendBodyAndHeaders("direct:verify_exception_sig_userids", 
payload, headers);
+        assertMockEndpointsSatisfied();
+
+        //check exception text
+        Exception e = (Exception) 
exception.getExchanges().get(0).getProperty(Exchange.EXCEPTION_CAUGHT);
+        assertNotNull("Expected excpetion  missing", e);
+        assertTrue(e.getMessage().contains("No public key found fitting to the 
signature key Id"));
+
+    }
+    
+
+    @Test
+    public void 
testVerifyExceptionNoPassphraseSpecifiedForSignatureKeyUserId() throws 
Exception {
+        MockEndpoint exception = setupExpectations(context, 1, 
"mock:exception");
+
+        String payload = "Hi Alice, Be careful Eve is listening, signed Bob";
+        Map<String, Object> headers = new HashMap<String, Object>();
+        // add signature user id which does not have a passphrase
+        headers.put(PGPDataFormat.SIGNATURE_KEY_USERID, 
"userIDWithNoPassphrase");
+        // the following entry is necessary for the dynamic test
+        headers.put(PGPDataFormat.KEY_USERID, "second");
+        template.sendBodyAndHeaders("direct:several-signer-keys", payload, 
headers);
+        assertMockEndpointsSatisfied();
+
+        //check exception text
+        Exception e = (Exception) 
exception.getExchanges().get(0).getProperty(Exchange.EXCEPTION_CAUGHT);
+        assertNotNull("Expected excpetion  missing", e);
+        assertTrue(e.getMessage().contains("No passphrase specified for 
signature key user ID"));
+
+    }
+    
+ 
+
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
             public void configure() throws Exception {
+
+                
onException(IllegalArgumentException.class).handled(true).to("mock:exception");
+
                 // START SNIPPET: pgp-format
                 // Public Key FileName
                 String keyFileName = getKeyFileName();
@@ -147,7 +211,7 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpSignAndEncrypt.setKeyUserid(keyUserid);
                 pgpSignAndEncrypt.setSignatureKeyFileName(keyFileNameSec);
                 PGPPassphraseAccessor passphraseAccessor = 
getPassphraseAccessor();
-                pgpSignAndEncrypt.setSignatureKeyUserid(keyUserid);
+                pgpSignAndEncrypt.setSignatureKeyUserid("Super 
<[email protected]>"); // must be the exact user Id because passphrase is 
searched in accessor
                 pgpSignAndEncrypt.setPassphraseAccessor(passphraseAccessor);
                 pgpSignAndEncrypt.setProvider(getProvider());
                 pgpSignAndEncrypt.setAlgorithm(getAlgorithm());
@@ -159,10 +223,18 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpVerifyAndDecrypt.setPassword(keyPassword);
                 pgpVerifyAndDecrypt.setSignatureKeyFileName(keyFileName);
                 pgpVerifyAndDecrypt.setProvider(getProvider());
+                pgpVerifyAndDecrypt.setSignatureKeyUserid(keyUserid); // 
restrict verification to public keys with certain User ID
 
                 
from("direct:inline-sign").marshal(pgpSignAndEncrypt).to("mock:encrypted").unmarshal(pgpVerifyAndDecrypt)
                         .to("mock:unencrypted");
                 // END SNIPPET: pgp-format-signature
+
+                // test verifying exception, no public key found corresponding 
to signature key userIds
+                
from("direct:verify_exception_sig_userids").marshal(pgpSignAndEncrypt).to("mock:encrypted")
+                        
.setHeader(PGPDataFormat.SIGNATURE_KEY_USERIDS).constant(Arrays.asList(new 
String[] {"wrong1", "wrong2"}))
+                        
.setHeader(PGPDataFormat.SIGNATURE_KEY_USERID).constant("wrongUserID").unmarshal(pgpVerifyAndDecrypt)
+                        .to("mock:unencrypted");
+
                 /* ---- key ring as byte array -- */
                 // START SNIPPET: pgp-format-key-ring-byte-array
                 PGPDataFormat pgpEncryptByteArray = new PGPDataFormat();
@@ -177,8 +249,8 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 pgpDecryptByteArray.setPassphraseAccessor(passphraseAccessor);
                 pgpDecryptByteArray.setProvider(getProvider());
 
-                
from("direct:key-ring-byte-array").streamCaching().marshal(pgpEncryptByteArray).to("mock:encrypted").unmarshal(pgpDecryptByteArray)
-                        .to("mock:unencrypted");
+                
from("direct:key-ring-byte-array").streamCaching().marshal(pgpEncryptByteArray).to("mock:encrypted")
+                        .unmarshal(pgpDecryptByteArray).to("mock:unencrypted");
                 // END SNIPPET: pgp-format-key-ring-byte-array
 
                 // START SNIPPET: pgp-format-signature-key-ring-byte-array
@@ -196,6 +268,8 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                 
pgpVerifyAndDecryptByteArray.setPassphraseAccessor(passphraseAccessor);
                 
pgpVerifyAndDecryptByteArray.setEncryptionKeyRing(getSecKeyRing());
                 pgpVerifyAndDecryptByteArray.setProvider(getProvider());
+                // restrict verification to public keys with certain User ID
+                
pgpVerifyAndDecryptByteArray.setSignatureKeyUserids(getSignatureKeyUserIds());
 
                 from("direct:sign-key-ring-byte-array").streamCaching()
                 // encryption key ring can also be set as header
@@ -207,7 +281,76 @@ public class PGPDataFormatTest extends 
AbstractPGPDataFormatTest {
                         // 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-format-signature-key-ring-byte-array
+
+                // START SNIPPET: pgp-format-several-signer-keys
+                PGPDataFormat pgpSignAndEncryptSeveralSignerKeys = new 
PGPDataFormat();
+                pgpSignAndEncryptSeveralSignerKeys.setKeyUserid(keyUserid);
+                
pgpSignAndEncryptSeveralSignerKeys.setEncryptionKeyRing(getPublicKeyRing());
+                
pgpSignAndEncryptSeveralSignerKeys.setSignatureKeyRing(getSecKeyRing());
+
+                List<String> signerUserIds = new ArrayList<String>();
+                signerUserIds.add("Third (comment third) <[email protected]>");
+                signerUserIds.add("Second <[email protected]>");
+                
pgpSignAndEncryptSeveralSignerKeys.setSignatureKeyUserids(signerUserIds);
+
+                Map<String, String> userId2Passphrase = new HashMap<String, 
String>();
+                userId2Passphrase.put("Third (comment third) 
<[email protected]>", "sdude");
+                userId2Passphrase.put("Second <[email protected]>", "sdude");
+                PGPPassphraseAccessor passphraseAccessorSeveralKeys = new 
PGPPassphraseAccessorDefault(userId2Passphrase);
+                
pgpSignAndEncryptSeveralSignerKeys.setPassphraseAccessor(passphraseAccessorSeveralKeys);
+
+                PGPDataFormat pgpVerifyAndDecryptSeveralSignerKeys = new 
PGPDataFormat();
+                
pgpVerifyAndDecryptSeveralSignerKeys.setPassphraseAccessor(passphraseAccessor);
+                
pgpVerifyAndDecryptSeveralSignerKeys.setEncryptionKeyRing(getSecKeyRing());
+                
pgpVerifyAndDecryptSeveralSignerKeys.setSignatureKeyRing(getPublicKeyRing());
+                
pgpVerifyAndDecryptSeveralSignerKeys.setProvider(getProvider());
+                // only specify one expected signature
+                List<String> expectedSigUserIds = new ArrayList<String>();
+                expectedSigUserIds.add("Second <[email protected]>");
+                
pgpVerifyAndDecryptSeveralSignerKeys.setSignatureKeyUserids(expectedSigUserIds);
+                
from("direct:several-signer-keys").streamCaching().marshal(pgpSignAndEncryptSeveralSignerKeys).to("mock:encrypted")
+                        
.unmarshal(pgpVerifyAndDecryptSeveralSignerKeys).to("mock:unencrypted");
+                // END SNIPPET: pgp-format-several-signer-keys
+
+                // test encryption by several key and signing by serveral keys 
where the keys are specified by one User ID part
+                PGPDataFormat pgpSignAndEncryptOneUserIdWithServeralKeys = new 
PGPDataFormat();
+                
pgpSignAndEncryptOneUserIdWithServeralKeys.setEncryptionKeyRing(getPublicKeyRing());
+                
pgpSignAndEncryptOneUserIdWithServeralKeys.setSignatureKeyRing(getSecKeyRing());
+                // the two private keys have the same password therefore we do 
not need a passphrase accessor
+                
pgpSignAndEncryptOneUserIdWithServeralKeys.setPassword(getKeyPassword());
+
+                PGPDataFormat pgpVerifyAndDecryptOneUserIdWithServeralKeys = 
new PGPDataFormat();
+                
pgpVerifyAndDecryptOneUserIdWithServeralKeys.setPassword(getKeyPassword());
+                
pgpVerifyAndDecryptOneUserIdWithServeralKeys.setEncryptionKeyRing(getSecKeyRing());
+                
pgpVerifyAndDecryptOneUserIdWithServeralKeys.setSignatureKeyRing(getPublicKeyRing());
+                
pgpVerifyAndDecryptOneUserIdWithServeralKeys.setProvider(getProvider());
+                
pgpVerifyAndDecryptOneUserIdWithServeralKeys.setSignatureKeyUserids(expectedSigUserIds);
+                from("direct:one-userid-several-keys")
+                        // there are two keys which have a User ID which 
contains the string "econd"
+                        .setHeader(PGPDataFormat.KEY_USERID)
+                        .constant("econd")
+                        .setHeader(PGPDataFormat.SIGNATURE_KEY_USERID)
+                        .constant("econd")
+                        .marshal(pgpSignAndEncryptOneUserIdWithServeralKeys)
+                        // it is recommended to remove the header immediately 
when it is no longer needed
+                        .removeHeader(PGPDataFormat.KEY_USERID)
+                        .removeHeader(PGPDataFormat.SIGNATURE_KEY_USERID)
+                        .to("mock:encrypted")
+                        // only specify one expected signature key, to check 
the first signature
+                        .setHeader(PGPDataFormat.SIGNATURE_KEY_USERID)
+                        .constant("Second <[email protected]>")
+                        
.unmarshal(pgpVerifyAndDecryptOneUserIdWithServeralKeys)
+                        // do it again but now check the second signature key
+                        // there are two keys which have a User ID which 
contains the string "econd"
+                        
.setHeader(PGPDataFormat.KEY_USERID).constant("econd").setHeader(PGPDataFormat.SIGNATURE_KEY_USERID)
+                        
.constant("econd").marshal(pgpSignAndEncryptOneUserIdWithServeralKeys)
+                        // it is recommended to remove the header immediately 
when it is no longer needed
+                        
.removeHeader(PGPDataFormat.KEY_USERID).removeHeader(PGPDataFormat.SIGNATURE_KEY_USERID)
+                        // only specify one expected signature key, to check 
the second signature
+                        
.setHeader(PGPDataFormat.SIGNATURE_KEY_USERID).constant("Third (comment third) 
<[email protected]>")
+                        
.unmarshal(pgpVerifyAndDecryptOneUserIdWithServeralKeys).to("mock:unencrypted");
             }
+
         };
     }
 

Reply via email to