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;
>   }
>