You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@camel.apache.org by "Goyal, Arpit" <ar...@sap.com> on 2017/03/05 22:53:38 UTC
Using PGPDataFormat instead of Bouncy Castle code
Hello,
Have doubts about the PGP Encryption by using PGP Data Format.
- We have the following code using Bouncy Castle library to sign and encrypt the payload, given the private key and passphrase for Signing and public key for Encryption.
- Wanted to know if we replace it with PGPDataFormat (aka Camel Route), how can we represent the following fields:
o PGPSignature.BINARY_DOCUMENT
o PGPLiteralData.BINARY
Regards,
Arpit.
Current Legacy Code: (SECURITY_PROVIDER_NAME = BC)
public byte[] signAndEncrypt(byte[] signKey, String passphrase, byte[] encryptionPublicKey, byte[] message) throws EncryptionException {
// final result stream.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
PGPPublicKey encryptPublicKey = readPublicKey(PGPUtil.getDecoderStream(new ByteArrayInputStream(encryptionPublicKey)));
// Init encrypted data generator
PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5)
.setSecureRandom(new SecureRandom())
.setProvider(SECURITY_PROVIDER_NAME));
encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encryptPublicKey));
// start compression
PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP);
// start signature generator
PGPSecretKey pgpSecKey = readSecretKey(PGPUtil.getDecoderStream(new ByteArrayInputStream(signKey)));
PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
.setProvider(SECURITY_PROVIDER_NAME).build())
.setProvider(SECURITY_PROVIDER_NAME)
.build(passphrase.toCharArray()));
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
new JcaPGPContentSignerBuilder(pgpSecKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256).setProvider(SECURITY_PROVIDER_NAME));
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
// iterate to find first signature to use
for (Iterator i = pgpSecKey.getPublicKey().getUserIDs(); i.hasNext();) {
String userId = (String) i.next();
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, userId);
signatureGenerator.setHashedSubpackets(spGen.generate());
// Just the first one!
break;
}
try (
//message
InputStream contentStream = new ByteArrayInputStream(message);
//out data
DataOutputStream aos = new DataOutputStream(baos);
//encrypted out
OutputStream encryptedOut = encryptedDataGenerator.open(aos, new byte[DEFAULT_BUFFER_SIZE]);
//compressed out
OutputStream compressedOut = compressedDataGenerator.open(encryptedOut);) {
signatureGenerator.generateOnePassVersion(false).encode(compressedOut);
// Create the Literal Data generator output stream
PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator();
try (
// create output stream
OutputStream literalOut = literalDataGenerator.open(compressedOut, PGPLiteralData.BINARY, "pgp", new Date(), new byte[DEFAULT_BUFFER_SIZE])) {
// read input file and write to target file using a buffer
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = contentStream.read(buf)) != -1) {
literalOut.write(buf, 0, bytesRead);
signatureGenerator.update(buf, 0, bytesRead);
literalOut.flush();
}
}
// sign the message.
signatureGenerator.generate().encode(compressedOut);
}
} catch (IOException e) {
throw new EncryptionException(getLogMsg("Exception while signing and encrypting message with keys ids {0}, {1}", signingKeyID, encryptionKeyID), e);
} catch (org.bouncycastle.openpgp.PGPException e) {
throw new EncryptionException(getLogMsg("Exception while signing and encrypting message with keys ids {0}, {1}", signingKeyID, encryptionKeyID), e);
} catch (NoSuchProviderException e) {
throw new EncryptionException(getLogMsg("Invalid Provider Exception while signing and encrypting message with keys ids {0}, {1}", signingKeyID, encryptionKeyID), e);
} catch (InvalidCipherKeyException e) {
throw new EncryptionException(getLogMsg("Valid keys missing exception while signing and encrypting message with keys ids {0}, {1}", signingKeyID, encryptionKeyID), e);
}
return baos.toByteArray(); // cipher text.
}
private PGPSecretKey readSecretKey(InputStream in) throws IOException, NoSuchProviderException, org.bouncycastle.openpgp.PGPException, InvalidCipherKeyException {
PGPSecretKey sKey = null;
PGPSecretKeyRingCollection pgpPriv = new PGPSecretKeyRingCollection(in, new JcaKeyFingerprintCalculator());
// loop through the collection till we find a suitable key.
Iterator it = pgpPriv.getKeyRings();
PGPSecretKeyRing pbr = null;
while (sKey == null && it.hasNext()) {
Object readData = it.next();
if (readData instanceof PGPSecretKeyRing) {
pbr = (PGPSecretKeyRing) readData;
sKey = pbr.getSecretKey();
}
}
if (sKey == null) {
throw new InvalidCipherKeyException("No secret key found in specified key ring collection.");
}
return sKey;
}
Re: Using PGPDataFormat instead of Bouncy Castle code
Posted by Franz Paul Forsthofer <em...@googlemail.com>.
Hello Arpit,
if you look into the code of the component camel-crypto you find in the
class PgpKeyAccessDataFormat
sigGen.init(PGPSignature.BINARY_DOCUMENT, sigPrivateKey);
and
PGPLiteralDataGenerator litData = new PGPLiteralDataGenerator();
String fileName = findFileName(exchange);
OutputStream litOut = litData.open(comOut, PGPLiteralData.BINARY,
fileName, new Date(), new byte[BUFFER_SIZE]);
So Camel PGP uses the constants the same way as you do.
Hope this answers your question.
Best Regards Franz
On Sun, Mar 5, 2017 at 11:53 PM, Goyal, Arpit <ar...@sap.com> wrote:
> Hello,
>
> Have doubts about the PGP Encryption by using PGP Data Format.
>
>
> - We have the following code using Bouncy Castle library to sign
> and encrypt the payload, given the private key and passphrase for Signing
> and public key for Encryption.
>
> - Wanted to know if we replace it with PGPDataFormat (aka Camel
> Route), how can we represent the following fields:
>
> o PGPSignature.BINARY_DOCUMENT
>
> o PGPLiteralData.BINARY
>
> Regards,
> Arpit.
>
>
> Current Legacy Code: (SECURITY_PROVIDER_NAME = BC)
>
> public byte[] signAndEncrypt(byte[] signKey, String passphrase, byte[]
> encryptionPublicKey, byte[] message) throws EncryptionException {
>
> // final result stream.
> ByteArrayOutputStream baos = new ByteArrayOutputStream();
>
> try {
>
> PGPPublicKey encryptPublicKey = readPublicKey(PGPUtil.getDecoderStream(new
> ByteArrayInputStream(encryptionPublicKey)));
>
> // Init encrypted data generator
> PGPEncryptedDataGenerator encryptedDataGenerator = new
> PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(
> PGPEncryptedData.CAST5)
>
> .setSecureRandom(new SecureRandom())
>
> .setProvider(SECURITY_PROVIDER_NAME));
> encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMetho
> dGenerator(encryptPublicKey));
>
> // start compression
> PGPCompressedDataGenerator compressedDataGenerator = new
> PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP);
>
> // start signature generator
> PGPSecretKey pgpSecKey = readSecretKey(PGPUtil.getDecoderStream(new
> ByteArrayInputStream(signKey)));
>
> PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new
> JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProvider
> Builder()
>
> .setProvider(SECURITY_PROVIDER_NAME).build())
>
> .setProvider(SECURITY_PROVIDER_NAME)
>
> .build(passphrase.toCharArray()));
>
> PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
> new JcaPGPContentSignerBuilder(pgpSecKey.getPublicKey().getAlgorithm(),
> HashAlgorithmTags.SHA256).setProvider(SECURITY_PROVIDER_NAME));
>
> signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
>
> // iterate to find first signature to use
> for (Iterator i = pgpSecKey.getPublicKey().getUserIDs();
> i.hasNext();) {
> String userId = (String) i.next();
> PGPSignatureSubpacketGenerator spGen = new
> PGPSignatureSubpacketGenerator();
> spGen.setSignerUserID(false, userId);
> signatureGenerator.setHashedSubpackets(spGen.generate());
> // Just the first one!
> break;
> }
>
> try (
> //message
> InputStream contentStream = new ByteArrayInputStream(message);
> //out data
> DataOutputStream aos = new DataOutputStream(baos);
> //encrypted out
> OutputStream encryptedOut = encryptedDataGenerator.open(aos,
> new byte[DEFAULT_BUFFER_SIZE]);
> //compressed out
> OutputStream compressedOut = compressedDataGenerator.open(encryptedOut);)
> {
>
> signatureGenerator.generateOnePassVersion(false).
> encode(compressedOut);
>
> // Create the Literal Data generator output stream
> PGPLiteralDataGenerator literalDataGenerator = new
> PGPLiteralDataGenerator();
>
> try (
> // create output stream
> OutputStream literalOut = literalDataGenerator.open(compressedOut,
> PGPLiteralData.BINARY, "pgp", new Date(), new byte[DEFAULT_BUFFER_SIZE])) {
>
> // read input file and write to target file using a buffer
> byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
>
> int bytesRead = 0;
> while ((bytesRead = contentStream.read(buf)) != -1) {
> literalOut.write(buf, 0, bytesRead);
> signatureGenerator.update(buf, 0, bytesRead);
> literalOut.flush();
> }
> }
>
> // sign the message.
> signatureGenerator.generate().encode(compressedOut);
>
> }
> } catch (IOException e) {
> throw new EncryptionException(getLogMsg("Exception while signing
> and encrypting message with keys ids {0}, {1}", signingKeyID,
> encryptionKeyID), e);
> } catch (org.bouncycastle.openpgp.PGPException e) {
> throw new EncryptionException(getLogMsg("Exception while signing
> and encrypting message with keys ids {0}, {1}", signingKeyID,
> encryptionKeyID), e);
> } catch (NoSuchProviderException e) {
> throw new EncryptionException(getLogMsg("Invalid Provider Exception
> while signing and encrypting message with keys ids {0}, {1}", signingKeyID,
> encryptionKeyID), e);
> } catch (InvalidCipherKeyException e) {
> throw new EncryptionException(getLogMsg("Valid keys missing
> exception while signing and encrypting message with keys ids {0}, {1}",
> signingKeyID, encryptionKeyID), e);
> }
>
> return baos.toByteArray(); // cipher text.
> }
>
>
> private PGPSecretKey readSecretKey(InputStream in) throws IOException,
> NoSuchProviderException, org.bouncycastle.openpgp.PGPException,
> InvalidCipherKeyException {
>
> PGPSecretKey sKey = null;
>
> PGPSecretKeyRingCollection pgpPriv = new
> PGPSecretKeyRingCollection(in, new JcaKeyFingerprintCalculator());
>
> // loop through the collection till we find a suitable key.
> Iterator it = pgpPriv.getKeyRings();
> PGPSecretKeyRing pbr = null;
>
> while (sKey == null && it.hasNext()) {
> Object readData = it.next();
> if (readData instanceof PGPSecretKeyRing) {
> pbr = (PGPSecretKeyRing) readData;
> sKey = pbr.getSecretKey();
> }
> }
>
> if (sKey == null) {
> throw new InvalidCipherKeyException("No secret key found in
> specified key ring collection.");
> }
>
> return sKey;
> }
>