Updated Branches: refs/heads/camel-2.12.x 3b2da77ea -> d1d4b81a2
CAMEL-6875 Added PGPPassphraseAccessor to support more sophsiticate keyring 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/d8784008 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/d8784008 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/d8784008 Branch: refs/heads/camel-2.12.x Commit: d878400812f3b38620c1a645448a93fb0b75cc28 Parents: 3b2da77 Author: Willem Jiang <ningji...@apache.org> Authored: Mon Oct 21 18:05:02 2013 +0800 Committer: Willem Jiang <willem.ji...@gmail.com> Committed: Tue Oct 22 18:10:54 2013 +0800 ---------------------------------------------------------------------- .../camel/converter/crypto/PGPDataFormat.java | 122 ++++++++++---- .../converter/crypto/PGPDataFormatUtil.java | 163 ++++++++++++++++--- .../converter/crypto/PGPPassphraseAccessor.java | 34 ++++ .../crypto/PGPPassphraseAccessorDefault.java | 54 ++++++ .../converter/crypto/PGPDataFormatTest.java | 28 ++-- .../crypto/SpringPGPDataFormatTest.xml | 16 +- .../apache/camel/component/crypto/pubring.gpg | Bin 1184 -> 2814 bytes .../apache/camel/component/crypto/secring.gpg | Bin 2562 -> 5570 bytes 8 files changed, 343 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/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 e6d8921..c14c5c8 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 @@ -111,20 +111,30 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { private boolean armored; private boolean integrity = true; - - /** Digest algorithm for signing (marshal). - * Possible values are defined in {@link HashAlgorithmTags}. - * Default value is SHA1. + + /** + * Digest algorithm for signing (marshal). Possible values are defined in + * {@link HashAlgorithmTags}. Default value is SHA1. */ private int hashAlgorithm = HashAlgorithmTags.SHA1; - + /** - * Symmetric key algorithm for encryption (marschal). - * Possible values are defined in {@link SymmetricKeyAlgorithmTags}. - * Default value is CAST5. + * Symmetric key algorithm for encryption (marschal). Possible values are + * defined in {@link SymmetricKeyAlgorithmTags}. Default value is CAST5. */ private int algorithm = SymmetricKeyAlgorithmTags.CAST5; + /** + * If no passpharase 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() { } @@ -141,7 +151,15 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { } protected String findKeyPassword(Exchange exchange) { - return exchange.getIn().getHeader(KEY_PASSWORD, getPassword(), String.class); + 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; + } } protected String findSignatureKeyFileName(Exchange exchange) { @@ -157,9 +175,17 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { } protected String findSignatureKeyPassword(Exchange exchange) { - return exchange.getIn().getHeader(SIGNATURE_KEY_PASSWORD, getSignaturePassword(), String.class); + String sigPassword = exchange.getIn().getHeader(SIGNATURE_KEY_PASSWORD, getSignaturePassword(), String.class); + if (sigPassword != null) { + return sigPassword; + } + if (passphraseAccessor != null) { + return passphraseAccessor.getPassphrase(findSignatureKeyUserid(exchange)); + } else { + return null; + } } - + protected int findAlgorithm(Exchange exchange) { return exchange.getIn().getHeader(ENCRYPTION_ALGORITHM, getAlgorithm(), Integer.class); } @@ -231,13 +257,14 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { return null; } - PGPSecretKey sigSecretKey = PGPDataFormatUtil.findSecretKey(exchange.getContext(), sigKeyFileName, sigKeyRing, sigKeyPassword, getProvider()); + PGPSecretKey sigSecretKey = PGPDataFormatUtil.findSecretKey(exchange.getContext(), sigKeyFileName, sigKeyRing, sigKeyPassword, + sigKeyUserid, getProvider()); if (sigSecretKey == null) { throw new IllegalArgumentException("Signature secret key is null, cannot proceed"); } - PGPPrivateKey sigPrivateKey = sigSecretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(getProvider()).build( - sigKeyPassword.toCharArray())); + PGPPrivateKey sigPrivateKey = sigSecretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(getProvider()) + .build(sigKeyPassword.toCharArray())); if (sigPrivateKey == null) { throw new IllegalArgumentException("Signature private key is null, cannot proceed"); } @@ -259,15 +286,10 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { return null; } - PGPPrivateKey key = PGPDataFormatUtil.findPrivateKey(exchange.getContext(), findKeyFileName(exchange), - findEncryptionKeyRing(exchange), encryptedStream, findKeyPassword(exchange), getProvider()); - if (key == null) { - throw new IllegalArgumentException("Private key is null, cannot proceed"); - } - InputStream in; try { byte[] encryptedData = IOUtils.toByteArray(encryptedStream); + //TODO why do we need a byte array input stream? --> streaming not possible? InputStream byteStream = new ByteArrayInputStream(encryptedData); in = PGPUtil.getDecoderStream(byteStream); } finally { @@ -286,11 +308,21 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { } IOHelper.close(in); - PGPPublicKeyEncryptedData pbe = (PGPPublicKeyEncryptedData) enc.get(0); + PGPPublicKeyEncryptedData pbe = null; + PGPPrivateKey key = null; + // find encrypted data for which a private key exists in the secret key ring + for (int i = 0; i < enc.size() && key == null; i++) { + pbe = (PGPPublicKeyEncryptedData) enc.get(i); + key = PGPDataFormatUtil.findPrivateKeyWithKeyId(exchange.getContext(), findKeyFileName(exchange), + findEncryptionKeyRing(exchange), pbe.getKeyID(), findKeyPassword(exchange), getPassphraseAccessor(), getProvider()); + } + if (key == null) { + throw new PGPException("Provided input is encrypted with unknown pair of keys."); + } + InputStream encData = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(getProvider()).build(key)); pgpFactory = new PGPObjectFactory(encData); PGPCompressedData comData = (PGPCompressedData) pgpFactory.nextObject(); - pgpFactory = new PGPObjectFactory(comData.getDataStream()); Object object = pgpFactory.nextObject(); @@ -305,6 +337,7 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { PGPLiteralData ld = (PGPLiteralData) object; InputStream litData = ld.getInputStream(); + //TODO we should enable streaming here with CashedOutputStream!! byte[] answer; try { answer = Streams.readAll(litData); @@ -315,7 +348,7 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { if (signature != null) { signature.update(answer); PGPSignatureList sigList = (PGPSignatureList) pgpFactory.nextObject(); - if (!signature.verify(sigList.get(0))) { + if (!signature.verify(getSignatureWithKeyId(signature.getKeyID(), sigList))) { throw new SignatureException("Cannot verify PGP signature"); } } @@ -323,18 +356,37 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { return answer; } + protected PGPSignature getSignatureWithKeyId(long keyID, PGPSignatureList sigList) { + for (int i = 0; i < sigList.size(); i++) { + PGPSignature signature = sigList.get(i); + if (keyID == signature.getKeyID()) { + return signature; + } + } + throw new IllegalStateException("PGP signature is inconsistent"); + } + protected PGPOnePassSignature getSignature(Exchange exchange, PGPOnePassSignatureList signatureList) throws IOException, PGPException, NoSuchProviderException { - PGPPublicKey sigPublicKey = PGPDataFormatUtil.findPublicKey(exchange.getContext(), findSignatureKeyFileName(exchange), - findSignatureKeyRing(exchange), findSignatureKeyUserid(exchange), false); - if (sigPublicKey == null) { - throw new IllegalArgumentException("Signature public key is null, cannot proceed"); + for (int i = 0; i < signatureList.size(); i++) { + PGPOnePassSignature signature = signatureList.get(i); + // Determine public key from signature keyId + PGPPublicKey sigPublicKey = PGPDataFormatUtil.findPublicKeyWithKeyId(exchange.getContext(), findSignatureKeyFileName(exchange), + findSignatureKeyRing(exchange), signature.getKeyID(), false); + if (sigPublicKey == null) { + continue; + } + // choose that signature for which a public key exists! + signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider(getProvider()), sigPublicKey); + return signature; + } + if (signatureList.isEmpty()) { + return null; + } else { + throw new IllegalArgumentException("No public key found fitting to the signature key Id; cannot verify the signature"); } - PGPOnePassSignature signature = signatureList.get(0); - signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider(getProvider()), sigPublicKey); - return signature; } /** @@ -448,8 +500,6 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { public void setProvider(String provider) { this.provider = provider; } - - public int getHashAlgorithm() { return hashAlgorithm; @@ -467,6 +517,14 @@ public class PGPDataFormat extends ServiceSupport implements DataFormat { this.algorithm = algorithm; } + public PGPPassphraseAccessor getPassphraseAccessor() { + return passphraseAccessor; + } + + public void setPassphraseAccessor(PGPPassphraseAccessor passphraseAccessor) { + this.passphraseAccessor = passphraseAccessor; + } + @Override protected void doStart() throws Exception { if (Security.getProvider(BC) == null && BC.equals(getProvider())) { http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/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 1dfa33a..bff00ad 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 @@ -50,8 +50,9 @@ public final class PGPDataFormatUtil { private PGPDataFormatUtil() { } - public static PGPPublicKey findPublicKey(CamelContext context, String filename, String userid, boolean forEncryption) throws IOException, PGPException, - NoSuchProviderException { + @Deprecated + public static PGPPublicKey findPublicKey(CamelContext context, String filename, String userid, boolean forEncryption) + throws IOException, PGPException, NoSuchProviderException { return findPublicKey(context, filename, null, userid, forEncryption); } @@ -68,6 +69,57 @@ public final class PGPDataFormatUtil { return pubKey; } + public static PGPPublicKey findPublicKeyWithKeyId(CamelContext context, String filename, byte[] keyRing, long keyid, + boolean forEncryption) throws IOException, PGPException, NoSuchProviderException { + InputStream is = determineKeyRingInputStream(context, filename, keyRing, forEncryption); + PGPPublicKey pubKey; + try { + pubKey = findPublicKeyWithKeyId(is, keyid); + } finally { + IOHelper.close(is); + } + return pubKey; + } + + public static PGPPrivateKey findPrivateKeyWithKeyId(CamelContext context, String filename, byte[] secreteKeyRing, long keyid, + String passphrase, PGPPassphraseAccessor passpraseAccessor, String provider) throws IOException, PGPException, + NoSuchProviderException { + InputStream is = determineKeyRingInputStream(context, filename, secreteKeyRing, true); + try { + return findPrivateKeyWithKeyId(is, keyid, passphrase, passpraseAccessor, provider); + } finally { + IOHelper.close(is); + } + } + + private static PGPPrivateKey findPrivateKeyWithKeyId(InputStream keyringInput, long keyid, String passphrase, + 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; + PGPSecretKey secKey = keyring.getSecretKey(); + if (secKey != null && keyid == secKey.getKeyID()) { + if (passphrase == null && passphraseAccessor != null) { + // get passphrase from accessor + @SuppressWarnings("unchecked") + Iterator<String> userIDs = secKey.getUserIDs(); + while (passphrase == null && userIDs.hasNext()) { + passphrase = passphraseAccessor.getPassphrase(userIDs.next()); + } + } + PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build( + passphrase.toCharArray())); + if (privateKey != null) { + return privateKey; + } + } + } + } + return null; + } + private static InputStream determineKeyRingInputStream(CamelContext context, String filename, byte[] keyRing, boolean forEncryption) throws IOException { if (filename != null && keyRing != null) { @@ -90,6 +142,24 @@ public final class PGPDataFormatUtil { } @SuppressWarnings("unchecked") + private static PGPPublicKey findPublicKeyWithKeyId(InputStream input, long keyid) throws IOException, PGPException, + 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; + } + } + } + + return null; + } + + @SuppressWarnings("unchecked") private static PGPPublicKey findPublicKey(InputStream input, String userid, boolean forEncryption) throws IOException, PGPException, NoSuchProviderException { PGPPublicKeyRingCollection pgpSec = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input)); @@ -99,17 +169,17 @@ public final class PGPDataFormatUtil { PGPPublicKeyRing keyRing = keyRingIter.next(); Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys(); - String keyUserId = null; while (keyIter.hasNext()) { PGPPublicKey key = keyIter.next(); for (Iterator<String> iterator = key.getUserIDs(); iterator.hasNext();) { - keyUserId = iterator.next(); - } - if (keyUserId != null && keyUserId.contains(userid)) { - if (forEncryption && key.isEncryptionKey()) { - return key; - } else if (!forEncryption && isSignatureKey(key)) { - return key; + 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; + } } } } @@ -123,26 +193,36 @@ public final class PGPDataFormatUtil { return algorithm == RSA_GENERAL || algorithm == RSA_SIGN || algorithm == DSA || algorithm == ECDSA || algorithm == ELGAMAL_GENERAL; } + @Deprecated public static PGPPrivateKey findPrivateKey(CamelContext context, String keychainFilename, InputStream encryptedInput, String passphrase) throws IOException, PGPException, NoSuchProviderException { return findPrivateKey(context, keychainFilename, null, encryptedInput, passphrase, "BC"); } + @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 keyChainInputStream = determineKeyRingInputStream(context, keychainFilename, secKeyRing, true); PGPPrivateKey privKey = null; try { - privKey = findPrivateKey(keyChainInputStream, encryptedInput, passphrase, provider); + privKey = findPrivateKey(keyChainInputStream, encryptedInput, passphrase, passphraseAccessor, provider); } finally { IOHelper.close(keyChainInputStream); } return privKey; } - private static PGPPrivateKey findPrivateKey(InputStream keyringInput, InputStream encryptedInput, String passphrase, String provider) throws IOException, - PGPException, NoSuchProviderException { + @Deprecated + private static PGPPrivateKey findPrivateKey(InputStream keyringInput, InputStream encryptedInput, String passphrase, + PGPPassphraseAccessor passphraseAccessor, String provider) throws IOException, PGPException, NoSuchProviderException { PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput)); PGPObjectFactory factory = new PGPObjectFactory(PGPUtil.getDecoderStream(encryptedInput)); PGPEncryptedDataList enc; @@ -163,7 +243,16 @@ public final class PGPDataFormatUtil { encryptedData = (PGPPublicKeyEncryptedData) encryptedDataObjects.next(); PGPSecretKey pgpSecKey = pgpSec.getSecretKey(encryptedData.getKeyID()); if (pgpSecKey != null) { - privateKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(passphrase.toCharArray())); + if (passphrase == null && passphraseAccessor != null) { + // get passphrase from accessor + @SuppressWarnings("unchecked") + Iterator<String> userIDs = pgpSecKey.getUserIDs(); + while (passphrase == null && userIDs.hasNext()) { + passphrase = passphraseAccessor.getPassphrase(userIDs.next()); + } + } + privateKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build( + passphrase.toCharArray())); } } if (privateKey == null && pgpSec.size() > 0 && encryptedData != null) { @@ -172,25 +261,34 @@ public final class PGPDataFormatUtil { return privateKey; } - public static PGPSecretKey findSecretKey(CamelContext context, String keychainFilename, String passphrase) - throws IOException, PGPException, NoSuchProviderException { + @Deprecated + public static PGPSecretKey findSecretKey(CamelContext context, String keychainFilename, String passphrase) throws IOException, + PGPException, NoSuchProviderException { return findSecretKey(context, keychainFilename, null, passphrase, "BC"); } - public static PGPSecretKey findSecretKey(CamelContext context, String keychainFilename, byte[] secKeyRing, String passphrase, String provider) - throws IOException, PGPException, NoSuchProviderException { - + public static PGPSecretKey findSecretKey(CamelContext context, String keychainFilename, byte[] secKeyRing, String passphrase, + String userId, String provider) throws IOException, PGPException, NoSuchProviderException { InputStream keyChainInputStream = determineKeyRingInputStream(context, keychainFilename, secKeyRing, false); PGPSecretKey secKey = null; try { - secKey = findSecretKey(keyChainInputStream, passphrase, provider); + secKey = findSecretKey(keyChainInputStream, passphrase, userId, provider); } finally { IOHelper.close(keyChainInputStream); } return secKey; } - private static PGPSecretKey findSecretKey(InputStream keyringInput, String passphrase, String provider) throws IOException, PGPException, NoSuchProviderException { + @Deprecated + public static PGPSecretKey findSecretKey(CamelContext context, String keychainFilename, byte[] secKeyRing, String passphrase, + 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; PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput)); for (Iterator<?> i = pgpSec.getKeyRings(); i.hasNext() && pgpSecKey == null;) { @@ -198,9 +296,24 @@ public final class PGPDataFormatUtil { if (data instanceof PGPSecretKeyRing) { PGPSecretKeyRing keyring = (PGPSecretKeyRing) data; PGPSecretKey secKey = keyring.getSecretKey(); - PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(passphrase.toCharArray())); - if (privateKey != null) { - pgpSecKey = secKey; + if (userId != null) { + for (Iterator<String> iterator = secKey.getUserIDs(); iterator.hasNext();) { + String keyUserId = iterator.next(); + // there can be serveral user IDs! + if (keyUserId != null && keyUserId.contains(userId)) { + PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider) + .build(passphrase.toCharArray())); + if (privateKey != null) { + return secKey; + } + } + } + } else { + PGPPrivateKey privateKey = secKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build( + passphrase.toCharArray())); + if (privateKey != null) { + pgpSecKey = secKey; + } } } } http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessor.java ---------------------------------------------------------------------- diff --git a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessor.java b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessor.java new file mode 100644 index 0000000..4bd6b8f --- /dev/null +++ b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessor.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.converter.crypto; + +/** + * Access to the password for a user Id. + * + */ +public interface PGPPassphraseAccessor { + + /** + * Returns the passphrase for a user Id + * + * @param userId + * user Id, can be <code>null</code> + * @return the passphrase for the user Id, or <code>null</code> if the + * passphrase cannot be found + */ + String getPassphrase(String userId); +} http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessorDefault.java ---------------------------------------------------------------------- diff --git a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessorDefault.java b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessorDefault.java new file mode 100644 index 0000000..6796ccd --- /dev/null +++ b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/PGPPassphraseAccessorDefault.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.converter.crypto; + +import java.util.Map; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import org.apache.camel.util.ObjectHelper; + +public class PGPPassphraseAccessorDefault implements PGPPassphraseAccessor { + + private final Map<String, String> userId2Passphrase; + + public PGPPassphraseAccessorDefault(Map<String, String> userId2Passphrase) { + ObjectHelper.notNull(userId2Passphrase, "userIdPassphrase"); + + this.userId2Passphrase = userId2Passphrase; + } + + @Override + public String getPassphrase(String userId) { + return userId2Passphrase.get(userId); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/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 e890d53..a739a42 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,6 +19,8 @@ package org.apache.camel.converter.crypto; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Collections; +import java.util.Map; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.util.IOHelper; @@ -106,7 +108,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { from("direct:inline") .marshal().pgp(keyFileName, keyUserid) .to("mock:encrypted") - .unmarshal().pgp(keyFileNameSec, keyUserid, keyPassword) + .unmarshal().pgp(keyFileNameSec, null, keyPassword) .to("mock:unencrypted"); // END SNIPPET: pgp-format @@ -119,7 +121,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { PGPDataFormat pgpDecrypt = new PGPDataFormat(); pgpDecrypt.setKeyFileName(keyFileNameSec); - pgpDecrypt.setKeyUserid(keyUserid); + // pgpDecrypt.setKeyUserid(keyUserid); pgpDecrypt.setPassword(keyPassword); pgpDecrypt.setProvider(getProvider()); @@ -132,7 +134,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { from("direct:inline-armor") .marshal().pgp(keyFileName, keyUserid, null, true, true) .to("mock:encrypted") - .unmarshal().pgp(keyFileNameSec, keyUserid, keyPassword, true, true) + .unmarshal().pgp(keyFileNameSec, null, keyPassword, true, true) .to("mock:unencrypted"); // END SNIPPET: pgp-format-header @@ -141,8 +143,9 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { pgpSignAndEncrypt.setKeyFileName(keyFileName); pgpSignAndEncrypt.setKeyUserid(keyUserid); pgpSignAndEncrypt.setSignatureKeyFileName(keyFileNameSec); + PGPPassphraseAccessor passphraseAccessor = getPassphraseAccessor(); pgpSignAndEncrypt.setSignatureKeyUserid(keyUserid); - pgpSignAndEncrypt.setSignaturePassword(keyPassword); + pgpSignAndEncrypt.setPassphraseAccessor(passphraseAccessor); pgpSignAndEncrypt.setProvider(getProvider()); pgpSignAndEncrypt.setAlgorithm(getAlgorithm()); pgpSignAndEncrypt.setHashAlgorithm(getHashAlgorithm()); @@ -150,10 +153,8 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { PGPDataFormat pgpVerifyAndDecrypt = new PGPDataFormat(); pgpVerifyAndDecrypt.setKeyFileName(keyFileNameSec); - pgpVerifyAndDecrypt.setKeyUserid(keyUserid); pgpVerifyAndDecrypt.setPassword(keyPassword); pgpVerifyAndDecrypt.setSignatureKeyFileName(keyFileName); - pgpVerifyAndDecrypt.setSignatureKeyUserid(keyUserid); pgpVerifyAndDecrypt.setProvider(getProvider()); from("direct:inline-sign") @@ -172,8 +173,7 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { PGPDataFormat pgpDecryptByteArray = new PGPDataFormat(); pgpDecryptByteArray.setEncryptionKeyRing(getSecKeyRing()); - pgpDecryptByteArray.setKeyUserid(keyUserid); - pgpDecryptByteArray.setPassword(keyPassword); + pgpDecryptByteArray.setPassphraseAccessor(passphraseAccessor); pgpDecryptByteArray.setProvider(getProvider()); from("direct:key-ring-byte-array").marshal(pgpEncryptByteArray).to("mock:encrypted").unmarshal(pgpDecryptByteArray) @@ -191,10 +191,8 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { pgpSignAndEncryptByteArray.setHashAlgorithm(HashAlgorithmTags.RIPEMD160); PGPDataFormat pgpVerifyAndDecryptByteArray = new PGPDataFormat(); - pgpVerifyAndDecryptByteArray.setKeyUserid(keyUserid); - pgpVerifyAndDecryptByteArray.setPassword(keyPassword); + pgpVerifyAndDecryptByteArray.setPassphraseAccessor(passphraseAccessor); pgpVerifyAndDecryptByteArray.setEncryptionKeyRing(getSecKeyRing()); - pgpVerifyAndDecryptByteArray.setSignatureKeyUserid(keyUserid); pgpVerifyAndDecryptByteArray.setProvider(getProvider()); from("direct:sign-key-ring-byte-array") @@ -208,6 +206,8 @@ public class PGPDataFormatTest extends AbstractPGPDataFormatTest { .removeHeader(PGPDataFormat.SIGNATURE_KEY_RING).to("mock:unencrypted"); // END SNIPPET: pgp-format-signature-key-ring-byte-array } + + }; } @@ -226,5 +226,11 @@ 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); + return passphraseAccessor; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/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 38d8c39..fcc15ac 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 @@ -28,7 +28,7 @@ <pgp id="encrypt" keyFileName="org/apache/camel/component/crypto/pubring.gpg" keyUserid="sd...@nowhere.net"/> <pgp id="decrypt" keyFileName="org/apache/camel/component/crypto/secring.gpg" - keyUserid="sd...@nowhere.net" password="sdude"/> + password="sdude"/> </dataFormats> <route> @@ -56,20 +56,24 @@ <property name="algorithm" value="7"/> <!-- AES128 algorithm --> </bean> - <bean id="decryptBean" class="org.apache.camel.converter.crypto.PGPDataFormat"> - <property name="keyUserid" value="sd...@nowhere.net"/> + <bean id="decryptBean" class="org.apache.camel.converter.crypto.PGPDataFormat"> <property name="encryptionKeyRing" ref="secKeyRing"/> - <property name="password" value="sdude"/> + <property name="passphraseAccessor" ref="passphraseAccessorBean"/> </bean> - <!-- bean represents the publik key ring as byte array --> + <!-- bean represents the public key ring as byte array --> <bean id="pubKeyRing" class="org.apache.camel.converter.crypto.PGPDataFormatTest" factory-method="getPublicKeyRing" /> - <!-- bean represents the secure key ring as byte array --> + <!-- bean represents the secret key ring as byte array --> <bean id="secKeyRing" class="org.apache.camel.converter.crypto.PGPDataFormatTest" factory-method="getSecKeyRing" /> + + <!-- bean passphrase accessor --> + <bean id="passphraseAccessorBean" + class="org.apache.camel.converter.crypto.PGPDataFormatTest" + factory-method="getPassphraseAccessor" /> <!-- END SNIPPET: pgp-xml-data-format-bean-with-keyring-bytearray --> </beans> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubring.gpg ---------------------------------------------------------------------- diff --git a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubring.gpg b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubring.gpg index 4b3e405..21029c6 100644 Binary files a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubring.gpg and b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/pubring.gpg differ http://git-wip-us.apache.org/repos/asf/camel/blob/d8784008/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secring.gpg ---------------------------------------------------------------------- diff --git a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secring.gpg b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secring.gpg index d631be3..36af553 100644 Binary files a/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secring.gpg and b/components/camel-crypto/src/test/resources/org/apache/camel/component/crypto/secring.gpg differ