You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2014/02/12 04:19:12 UTC
git commit: CAMEL-7192 Supported the Sub-Key in PGPDataFormat with
thanks to Franz
Updated Branches:
refs/heads/master a1ec5e356 -> 1272f96c7
CAMEL-7192 Supported the Sub-Key in PGPDataFormat with thanks to Franz
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/1272f96c
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/1272f96c
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/1272f96c
Branch: refs/heads/master
Commit: 1272f96c7210ec44ea6934eeabd198c3b81207c0
Parents: a1ec5e3
Author: Willem Jiang <wi...@gmail.com>
Authored: Wed Feb 12 11:18:11 2014 +0800
Committer: Willem Jiang <wi...@gmail.com>
Committed: Wed Feb 12 11:18:11 2014 +0800
----------------------------------------------------------------------
.../camel/converter/crypto/PGPDataFormat.java | 16 ++
.../converter/crypto/PGPDataFormatUtil.java | 197 ++++++++++++++-----
.../converter/crypto/PGPDataFormatTest.java | 55 +++++-
.../camel/component/crypto/pubringSubKeys.gpg | Bin 0 -> 2020 bytes
.../camel/component/crypto/secringSubKeys.gpg | Bin 0 -> 4087 bytes
5 files changed, 209 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/1272f96c/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 0157088..d7e92b2 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
@@ -94,6 +94,18 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat {
public static final String SIGNATURE_HASH_ALGORITHM = "CamelPGPDataFormatSignatureHashAlgorithm";
public static final String COMPRESSION_ALGORITHM = "CamelPGPDataFormatCompressionAlgorithm";
+ /**
+ * During encryption the number of asymmectirc encryption keys is set to
+ * this header parameter. The Value is of type Integer.
+ */
+ public static final String NUMBER_OF_ENCRYPTION_KEYS = "CamelPGPDataFormatNumberOfEncryptionKeys";
+ /**
+ * During signing the number of signing keys is set to this header
+ * parameter. This corresponds to the number of signatures. The Value is of
+ * type Integer.
+ */
+ public static final String NUMBER_OF_SIGNING_KEYS = "CamelPGPDataFormatNumberOfSigningKeys";
+
private static final Logger LOG = LoggerFactory.getLogger(PGPDataFormat.class);
private static final String BC = "BC";
@@ -210,6 +222,7 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat {
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.");
}
+ exchange.getOut().setHeader(NUMBER_OF_ENCRYPTION_KEYS, Integer.valueOf(keys.size()));
InputStream input = ExchangeHelper.convertToMandatoryType(exchange, InputStream.class, graph);
@@ -324,6 +337,8 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat {
List<PGPSecretKeyAndPrivateKeyAndUserId> sigSecretKeysWithPrivateKeyAndUserId = determineSecretKeysWithPrivateKeyAndUserId(
exchange, sigKeyFileName, sigKeyUserids, sigKeyPassword, sigKeyRing);
+ exchange.getOut().setHeader(NUMBER_OF_SIGNING_KEYS, Integer.valueOf(sigSecretKeysWithPrivateKeyAndUserId.size()));
+
List<PGPSignatureGenerator> sigGens = new ArrayList<PGPSignatureGenerator>();
for (PGPSecretKeyAndPrivateKeyAndUserId sigSecretKeyWithPrivateKeyAndUserId : sigSecretKeysWithPrivateKeyAndUserId) {
PGPPrivateKey sigPrivateKey = sigSecretKeyWithPrivateKeyAndUserId.getPrivateKey();
@@ -342,6 +357,7 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat {
return sigGens;
}
+
public List<PGPSecretKeyAndPrivateKeyAndUserId> determineSecretKeysWithPrivateKeyAndUserId(Exchange exchange, String sigKeyFileName,
List<String> sigKeyUserids, String sigKeyPassword, byte[] sigKeyRing) throws IOException, PGPException, NoSuchProviderException {
http://git-wip-us.apache.org/repos/asf/camel/blob/1272f96c/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 3408a4a..b09ebe8 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
@@ -31,6 +31,7 @@ import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ResourceHelper;
+import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPObjectFactory;
@@ -42,6 +43,8 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.slf4j.Logger;
@@ -54,7 +57,7 @@ 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() {
@@ -86,7 +89,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);
@@ -96,7 +99,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 {
@@ -108,8 +111,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);
@@ -120,31 +123,30 @@ 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();
if (data instanceof PGPSecretKeyRing) {
PGPSecretKeyRing keyring = (PGPSecretKeyRing) data;
- for (Iterator<PGPSecretKey> secKeys = keyring.getSecretKeys(); secKeys.hasNext();) {
- PGPSecretKey secKey = secKeys.next();
- if (secKey != null && keyid == secKey.getKeyID()) {
- if (passphrase == null && passphraseAccessor != null) {
- // get passphrase from accessor
- Iterator<String> userIDs = secKey.getUserIDs();
- while (passphrase == null && userIDs.hasNext()) {
- passphrase = passphraseAccessor.getPassphrase(userIDs.next());
- }
+ PGPSecretKey secKey = keyring.getSecretKey(keyid);
+ if (secKey != null) {
+ if (passphrase == null && passphraseAccessor != null) {
+ // get passphrase from accessor // only primary/master key has user IDS
+ Iterator<String> userIDs = keyring.getSecretKey().getUserIDs();
+ while (passphrase == null && userIDs.hasNext()) {
+ passphrase = passphraseAccessor.getPassphrase(userIDs.next());
}
- if (passphrase != null) {
- PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(
- passphrase.toCharArray()));
- if (privateKey != null) {
- return privateKey;
- }
+ }
+ if (passphrase != null) {
+ PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider)
+ .build(passphrase.toCharArray()));
+ if (privateKey != null) {
+ return privateKey;
}
}
}
+
}
}
return null;
@@ -173,24 +175,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();
+ 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));
@@ -203,11 +205,15 @@ public final class PGPDataFormatUtil {
for (String useridPart : userids) {
for (String keyUserId : keyUserIds) {
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 });
+ if (forEncryption) {
+ if (isEncryptionKey(key)) {
+ LOG.debug(
+ "Public encryption key with key user ID {} and key ID {} found for specified user ID part {}",
+ new Object[] {keyUserId, Long.toString(key.getKeyID()), useridPart });
+ result.add(key);
+ }
} else if (!forEncryption && isSignatureKey(key)) {
+ // not used!
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 });
@@ -221,6 +227,24 @@ public final class PGPDataFormatUtil {
return result;
}
+ private static boolean isEncryptionKey(PGPPublicKey key) {
+ if (!key.isEncryptionKey()) {
+ return false;
+ }
+ //check keyflags
+ Boolean hasEncryptionKeyFlags = hasOneOfExpectedKeyFlags(key, new int[] {KeyFlags.ENCRYPT_COMMS, KeyFlags.ENCRYPT_STORAGE });
+ if (hasEncryptionKeyFlags != null && !hasEncryptionKeyFlags) {
+ LOG.debug(
+ "Public key with key key ID {} found for specified user ID. But this key will not be used for the encryption, because its key flags are not encryption key flags.",
+ new Object[] {Long.toString(key.getKeyID()) });
+ return false;
+ } else {
+ // also without keyflags (hasEncryptionKeyFlags = null), true is returned!
+ return true;
+ }
+
+ }
+
// Within a public keyring, the master / primary key has the user ID(s); the subkeys don't
// have user IDs associated directly to them, but the subkeys are implicitly associated with
// the user IDs of the master / primary key. The master / primary key is the first key in
@@ -238,6 +262,21 @@ public final class PGPDataFormatUtil {
return userIds;
}
+ // Within a secret keyring, the master / primary key has the user ID(s); the subkeys don't
+ // have user IDs associated directly to them, but the subkeys are implicitly associated with
+ // the user IDs of the master / primary key. The master / primary key is the first key in
+ // the keyring, and the rest of the keys are subkeys.
+ // http://bouncy-castle.1462172.n4.nabble.com/How-to-find-PGP-subkeys-td1465289.html
+ @SuppressWarnings("unchecked")
+ private static Set<String> getUserIds(PGPSecretKeyRing keyRing) {
+ Set<String> userIds = new LinkedHashSet<String>(3);
+ PGPSecretKey key = keyRing.getSecretKey();
+ for (Iterator<String> iterator = key.getUserIDs(); iterator.hasNext();) {
+ userIds.add(iterator.next());
+ }
+ return userIds;
+ }
+
private static boolean isSignatureKey(PGPPublicKey key) {
int algorithm = key.getAlgorithm();
return algorithm == RSA_GENERAL || algorithm == RSA_SIGN || algorithm == DSA || algorithm == ECDSA || algorithm == ELGAMAL_GENERAL;
@@ -251,14 +290,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;
@@ -272,7 +311,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;
@@ -313,13 +352,13 @@ 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);
try {
List<PGPSecretKeyAndPrivateKeyAndUserId> secKeys = findSecretKeysWithPrivateKeyAndUserId(keyChainInputStream,
@@ -334,8 +373,8 @@ public final class PGPDataFormatUtil {
}
public static List<PGPSecretKeyAndPrivateKeyAndUserId> findSecretKeysWithPrivateKeyAndUserId(CamelContext context,
- String keychainFilename, byte[] secKeyRing, Map<String, String> sigKeyUserId2Password, String provider) throws IOException,
- PGPException, NoSuchProviderException {
+ 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);
@@ -346,14 +385,14 @@ public final class PGPDataFormatUtil {
@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 List<PGPSecretKeyAndPrivateKeyAndUserId> findSecretKeysWithPrivateKeyAndUserId(InputStream keyringInput,
- Map<String, String> sigKeyUserId2Password, String provider) throws IOException, PGPException, NoSuchProviderException {
+ 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));
@@ -361,19 +400,23 @@ public final class PGPDataFormatUtil {
Object data = i.next();
if (data instanceof PGPSecretKeyRing) {
PGPSecretKeyRing keyring = (PGPSecretKeyRing) data;
- PGPSecretKey secKey = keyring.getSecretKey();
- 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(userIdPart)) {
- PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider)
- .build(sigKeyUserId2Password.get(userIdPart).toCharArray()));
- if (privateKey != null) {
- 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});
+ Set<String> keyUserIds = getUserIds(keyring);
+ for (String userIdPart : sigKeyUserId2Password.keySet()) {
+ for (String keyUserId : keyUserIds) {
+ if (keyUserId.contains(userIdPart)) {
+ for (Iterator<PGPSecretKey> iterKey = keyring.getSecretKeys(); iterKey.hasNext();) {
+ PGPSecretKey secKey = iterKey.next();
+ if (isSigningKey(secKey)) {
+ PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(
+ provider).build(sigKeyUserId2Password.get(userIdPart).toCharArray()));
+ if (privateKey != null) {
+ 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 });
+
+ }
+ }
}
}
}
@@ -383,6 +426,58 @@ public final class PGPDataFormatUtil {
return result;
}
+ private static boolean isSigningKey(PGPSecretKey secKey) {
+ if (!secKey.isSigningKey()) {
+ return false;
+ }
+ Boolean hasSigningKeyFlag = hasOneOfExpectedKeyFlags(secKey.getPublicKey(), new int[] {KeyFlags.SIGN_DATA });
+ if (hasSigningKeyFlag != null && !hasSigningKeyFlag) {
+ // not a signing key --> ignore
+ LOG.debug(
+ "Secret key with key ID {} found for specified user ID part. But this key will not be used for signing because of its key flags.",
+ Long.toString(secKey.getKeyID()));
+ return false;
+ } else {
+ // also if there are not any keyflags (hasSigningKeyFlag=null), true is returned!
+ return true;
+ }
+
+ }
+
+ /**
+ * Checks whether one of the signatures of the key has one of the expected
+ * key flags
+ *
+ * @param key
+ * @return {@link Boolean#TRUE} if key has one of the expected flag,
+ * <code>null</code> if the key does not have any key flags,
+ * {@link Boolean#FALSE} if the key has none of the expected flags
+ */
+ private static Boolean hasOneOfExpectedKeyFlags(PGPPublicKey key, int[] expectedKeyFlags) {
+ boolean containsKeyFlags = false;
+ for (@SuppressWarnings("unchecked")
+ Iterator<PGPSignature> itsig = key.getSignatures(); itsig.hasNext();) {
+ PGPSignature sig = itsig.next();
+ PGPSignatureSubpacketVector subPacks = sig.getHashedSubPackets();
+ if (subPacks != null) {
+ int keyFlag = subPacks.getKeyFlags();
+ if (keyFlag > 0 && !containsKeyFlags) {
+ containsKeyFlags = true;
+ }
+ for (int expectdKeyFlag : expectedKeyFlags) {
+ int result = keyFlag & expectdKeyFlag;
+ if (result == expectdKeyFlag) {
+ return Boolean.TRUE;
+ }
+ }
+ }
+ }
+ if (containsKeyFlags) {
+ return Boolean.FALSE;
+ }
+ return null; // no key flag
+ }
+
public static class PGPSecretKeyAndPrivateKeyAndUserId {
private final PGPSecretKey secretKey;
http://git-wip-us.apache.org/repos/asf/camel/blob/1272f96c/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 b815882..1aa7f7f 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
@@ -27,12 +27,14 @@ import java.util.List;
import java.util.Map;
import org.apache.camel.Exchange;
+import org.apache.camel.Message;
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;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
+import org.bouncycastle.bcpg.sig.KeyFlags;
import org.junit.Test;
public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
@@ -120,7 +122,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
public void testSeveralSignerKeys() throws Exception {
doRoundTripEncryptionTests("direct:several-signer-keys");
}
-
+
@Test
public void testOneUserIdWithServeralKeys() throws Exception {
doRoundTripEncryptionTests("direct:one-userid-several-keys");
@@ -142,7 +144,6 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
assertTrue(e.getMessage().contains("No public key found fitting to the signature key Id"));
}
-
@Test
public void testVerifyExceptionNoPassphraseSpecifiedForSignatureKeyUserId() throws Exception {
@@ -163,11 +164,35 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
assertTrue(e.getMessage().contains("No passphrase specified for signature key user ID"));
}
-
-
- protected RouteBuilder createRouteBuilder() {
- return new RouteBuilder() {
+ /**
+ * You get three keys with the UserId "keyflag", a primary key and its two
+ * sub-keys. The sub-key with KeyFlag {@link KeyFlags#SIGN_DATA} should be
+ * used for signing and the sub-key with KeyFlag
+ * {@link KeyFlags#ENCRYPT_COMMS} or {@link KeyFlags#ENCRYPT_COMMS} or
+ * {@link KeyFlags#ENCRYPT_STORAGE} should be used for decryption.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testKeyFlagSelectsCorrectKey() throws Exception {
+ MockEndpoint mockKeyFlag = getMockEndpoint("mock:encrypted_keyflag");
+ mockKeyFlag.setExpectedMessageCount(1);
+ template.sendBody("direct:keyflag", "Test Message");
+ assertMockEndpointsSatisfied();
+
+ List<Exchange> exchanges = mockKeyFlag.getExchanges();
+ assertEquals(1, exchanges.size());
+ Exchange exchange = exchanges.get(0);
+ Message inMess = exchange.getIn();
+ assertNotNull(inMess);
+ // must contain exactly one encryption key and one signature
+ assertEquals(1, inMess.getHeader(PGPDataFormat.NUMBER_OF_ENCRYPTION_KEYS));
+ assertEquals(1, inMess.getHeader(PGPDataFormat.NUMBER_OF_SIGNING_KEYS));
+ }
+
+ protected RouteBuilder[] createRouteBuilders() {
+ return new RouteBuilder[] {new RouteBuilder() {
public void configure() throws Exception {
onException(IllegalArgumentException.class).handled(true).to("mock:exception");
@@ -231,7 +256,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
// 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_USERIDS).constant(Arrays.asList(new String[] {"wrong1", "wrong2" }))
.setHeader(PGPDataFormat.SIGNATURE_KEY_USERID).constant("wrongUserID").unmarshal(pgpVerifyAndDecrypt)
.to("mock:unencrypted");
@@ -349,9 +374,23 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest {
// only specify one expected signature key, to check the second signature
.setHeader(PGPDataFormat.SIGNATURE_KEY_USERID).constant("Third (comment third) <em...@third.com>")
.unmarshal(pgpVerifyAndDecryptOneUserIdWithServeralKeys).to("mock:unencrypted");
+
}
- };
+ }, new RouteBuilder() {
+ public void configure() throws Exception {
+ // keyflag test
+ PGPDataFormat pgpKeyFlag = new PGPDataFormat();
+ // the following keyring contains a primary key with KeyFlag "Certify" and a subkey for signing and a subkey for encryption
+ pgpKeyFlag.setKeyFileName("org/apache/camel/component/crypto/pubringSubKeys.gpg");
+ pgpKeyFlag.setSignatureKeyFileName("org/apache/camel/component/crypto/secringSubKeys.gpg");
+ pgpKeyFlag.setSignaturePassword("Abcd1234");
+ pgpKeyFlag.setKeyUserid("keyflag");
+ pgpKeyFlag.setSignatureKeyUserid("keyflag");
+
+ from("direct:keyflag").marshal(pgpKeyFlag).to("mock:encrypted_keyflag");
+ }
+ } };
}
public static byte[] getPublicKeyRing() throws Exception {
http://git-wip-us.apache.org/repos/asf/camel/blob/1272f96c/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubringSubKeys.gpg
----------------------------------------------------------------------
diff --git a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubringSubKeys.gpg b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubringSubKeys.gpg
new file mode 100644
index 0000000..93dbdf0
Binary files /dev/null and b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubringSubKeys.gpg differ
http://git-wip-us.apache.org/repos/asf/camel/blob/1272f96c/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secringSubKeys.gpg
----------------------------------------------------------------------
diff --git a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secringSubKeys.gpg b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secringSubKeys.gpg
new file mode 100644
index 0000000..2ecf6ee
Binary files /dev/null and b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secringSubKeys.gpg differ