title: Fail to gpg-decrypt BouncyCastlePGP-encrypted message
body: <p>When I try to decrypt a message using GnuPG encrypted with BouncyCastle I get two <code>gpg: [don't know]: invalid packet (ctb=xx)</code> messages and the decryption fails.</p>
  
  <p>I am using <code>BouncyCastle 1.54</code> and <code>gpg (GnuPG) 2.0.30 on OSX</code></p>
  
  <p><strong>Details</strong></p>
  
  <p><strong>1)</strong> The PGP key was generated using gpg as follows:</p>
  
  <pre><code>$ gpg --gen-key
  gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.
  
  Please select what kind of key you want:
     (1) RSA and RSA (default)
     (2) DSA and Elgamal
     (3) DSA (sign only)
     (4) RSA (sign only)
  Your selection? 1
  RSA keys may be between 1024 and 4096 bits long.
  What keysize do you want? (2048)
  Requested keysize is 2048 bits
  Please specify how long the key should be valid.
           0 = key does not expire
        &lt;n&gt;  = key expires in n days
        &lt;n&gt;w = key expires in n weeks
        &lt;n&gt;m = key expires in n months
        &lt;n&gt;y = key expires in n years
  Key is valid for? (0) 0
  Key does not expire at all
  Is this correct? (y/N) y
  
  GnuPG needs to construct a user ID to identify your key.
  
  Real name: Foo Bar
  Email address: foo@bar.com
  Comment: Test Key
  You selected this USER-ID:
      "Foo Bar (Test Key) &lt;foo@bar.com&gt;"
  
  Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
  You need a Passphrase to protect your secret key.
  
  We need to generate a lot of random bytes. It is a good idea to perform
  some other action (type on the keyboard, move the mouse, utilize the
  disks) during the prime generation; this gives the random number
  generator a better chance to gain enough entropy.
  We need to generate a lot of random bytes. It is a good idea to perform
  some other action (type on the keyboard, move the mouse, utilize the
  disks) during the prime generation; this gives the random number
  generator a better chance to gain enough entropy.
  public and secret key created and signed.
  
  pub   2048R/79CC322A 2017-08-17
        Key fingerprint = 93B9 0D06 08D2 EB84 9F83  4CD3 A470 748E 79CC 322A
  uid       [ unknown] Foo Bar (Test Key) &lt;foo@bar.com&gt;
  sub   2048R/21B41E21 2017-08-17
  $ 
  </code></pre>
  
  <p><strong>2)</strong> The PGP public key exported in asc form looks like:</p>
  
  <pre><code>-----BEGIN PGP PUBLIC KEY BLOCK-----
  Version: GnuPG v2
  
  mQENBFmWE88BCADB+esy+D2Zobru86ztUTp7hWyDy5w9B2iHlyORLI6mQ0JH+ya6
  cbaO9nWT7WC68l1ocWaeak0t/9hx0CDWv6zdAXfEUPu8qB53M4m1NACDJp3UDeQS
  UytmpB/kutViUO+yiRhtezYsFP70PHOO7o9Tgze5H/qF/hgAVmk1/eN4oSTH4hqo
  VIvlsvTNZYLt+a2wYN0RPPryfXnvrKOSXdE5roQd/TMaMwwd2Mbhhh31IB1ROw2/
  I+tvJfrM4zLseuo0ndYmWL7ZfjPslsFUezUQf5BDmFdIi9M3/UWHtHmSR6GGG1ko
  uo0XjABiIjwfj1mQSA3txI1yO+RLHYrI5UL1ABEBAAG0IEZvbyBCYXIgKFRlc3Qg
  S2V5KSA8Zm9vQGJhci5jb20+iQE5BBMBCAAjBQJZlhPPAhsDBwsJCAcDAgEGFQgC
  CQoLBBYCAwECHgECF4AACgkQpHB0jnnMMipk+Qf/cKLSdv+aYHKteS/rtAXQbRWG
  5nEGKk8vU5HseESr9tDbzkMpruYXtGG99GjPjZO2NqoYF+3NzD6suiQzP95dHyH0
  g3i2AHLoyd7W9VvZEieH7vGRrUjYYP2N/qifUepdiu3gKQLHDBE14tXRHEfTN5WV
  BxClZ4MwmMvHzsg6NB2RXJb7t5e9apgQ/+0O9l5LwGsSSkCQr53OmoMSUnQP0lrz
  gqMxzbC6sI/FYaVaoMGnAUMFQ+8l7nI/Tv6R/sCN5d4egcIC1AzVcDE+zGkwRrmX
  4lcKen0XvolJfpUNx9D2CIAQttz0nvygxjBAByXT4oFcbPw9GZCNmxKo/eUp4LkB
  DQRZlhPPAQgAz4tebylTFXZCj4xwzy7wyrw4J+vUkMrOh5tOVgISPMaEiDBzFyhf
  oqs0uAamImUyF2HGVGXEGappZncjrympdYFpDXG6jb0oYap03hheli1R6h+56PNq
  zNyVzlfq85BqgVa5Qed1VnDbEz29JMjLwSvCEY3V0SIOgVZxE5GfMjvAkUhPoE+o
  T5uVuRUlnfdKXMYgNRh5gbNEsvx+PMGihC3pSrWWYbBtU6otNXCVCYQryORaHWAf
  pvB99P6YzP0nc6Dbu2ZSiGsDAQwa3ZCow+E997upf22WMfowwkNFtarnrr1fVLkl
  exR28nJdeAbh0R3WpgQJqeCGmH9fYQEBjwARAQABiQEfBBgBCAAJBQJZlhPPAhsM
  AAoJEKRwdI55zDIqgAAH/39teAauUrB+xEVr/Q+McXa0PQSrErB2P4jaVIBuZH2/
  6EeRycp6bIwc5R/gpkIVcPg8DmDYtobRbj2YDc5o+4tPVgSKJUgOB2l9CryP+aCm
  lx8R0nCN8q53vqtmm7LYc+W1K6tXQJZi8VbCC9sLGUxH0HuDP2ldcBnrialV2cLZ
  zsxRgoFF3f8u/We97z2qwzRQXshvw4GVL3wSs511mTcOZW8LnO1YMt3m5ABIsZN0
  P/avr7zEqsvr0iJOQ7WbJLbgHkxKu03SfcN0XfVDX4VzqykLvn9THHVtofU6h4LE
  LoIRKGg57DXFrsc93a1GWzN9z764sXQ7JgWqnW6a72g=
  =n8OZ
  -----END PGP PUBLIC KEY BLOCK-----
  </code></pre>
  
  <p><strong>3)</strong> The PGP public key is passed in in its "PUBLIC KEY BLOCK"-form and resolved as follows:
  (the pgpKeyBytes are the UTF-8 byte encoding of the String representation of the key)</p>
  
  <pre><code>private PGPPublicKey resolvePgpPublicKey(byte[] pgpKeyBytes) throws IOException, PGPException {
    PGPPublicKeyRingCollection keyRingCollection;
    try (InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(pgpKeyBytes))) {
      keyRingCollection = new PGPPublicKeyRingCollection(
          PGPUtil.getDecoderStream(in), new JcaKeyFingerprintCalculator());
    }
  
    Iterator&lt;?&gt; keyRingIterator = keyRingCollection.getKeyRings();
    while (keyRingIterator.hasNext()) {
      PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIterator.next();
  
      Iterator&lt;?&gt; keyIterator = keyRing.getPublicKeys();
      while (keyIterator.hasNext()) {
        PGPPublicKey key = (PGPPublicKey) keyIterator.next();
        if (key.isMasterKey()) {
          continue;
        }
        if (key.isEncryptionKey()) {
          return key;
        }
      }
    }
    throw new ServiceRequestException("Cannot resolve PGPPublicKey");
  }
  </code></pre>
  
  <p><strong>4)</strong> What is getting PGP encrypted is the hex-string representation of a 16-byte array (passed in as
  keyBytes) as follows:</p>
  
  <pre><code>private byte[] encryptKeyBytes(byte[] keyBytes, byte[] pgpKey) throws GeneralSecurityException {
    ByteArrayOutputStream encKeyBytes = new ByteArrayOutputStream(keyBytes.length);
  
    try (Handle&lt;SecureRandom&gt; randomHandle = RngSupport.getRandom()) {
      JcePGPDataEncryptorBuilder encryptorBuilder =
          new JcePGPDataEncryptorBuilder(PGPEncryptedDataGenerator.AES_256);
      encryptorBuilder.setWithIntegrityPacket(true);
      encryptorBuilder.setSecureRandom(randomHandle.getObject());
      encryptorBuilder.setProvider("BC");
  
      PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator(encryptorBuilder);
      try {
        JcePublicKeyKeyEncryptionMethodGenerator keyEncryptionMethodGenerator =
            new JcePublicKeyKeyEncryptionMethodGenerator(resolvePgpPublicKey(pgpKey));
        keyEncryptionMethodGenerator.setProvider("BC");
        encryptor.addMethod(keyEncryptionMethodGenerator);
        try (
            OutputStream ao = new ArmoredOutputStream(encKeyBytes);
            OutputStream eo = encryptor.open(ao, keyBytes.length)) {
          eo.write(BytesSupport.encodeHex(keyBytes).getBytes(StandardCharsets.UTF_8));
        }
      } catch (ServiceRequestException e) {
        throw e;
      } catch (Exception e) {
        throw new GeneralSecurityException("Cannot perform PGP encryption", e);
      }
    }
  
    return encKeyBytes.toByteArray();
  }
  </code></pre>
  
  <p><strong>5)</strong> An example result of this encryption looks like:</p>
  
  <pre><code>-----BEGIN PGP MESSAGE-----
  Version: BCPG v@RELEASE_NAME@
  
  hQEMA0a1HkkhtB4hAQf+MfDa3ILJJivDYO+V9GwLDXMq1Oi8YFe/oNfScT2KT6aG
  rKBIaCQvwTQPD95QS3lo9sRZYvD64C7+Y+PA2e4nSJYNiLmyEczqFVzSgoI8ibhD
  LDG+trkAgEd3UiSltju8oF/d5SUPaubVrfH413xZ2xg5lbx7z78U4KtAZ1IMk/XN
  DN2nCaOVIw/EbqzVt8YCdDpQRrnfh1ZB5lDmLYoRuJykQ08UCrxv9dyQN3wpOX/G
  K7Nq3w6Q6+vT8LiP9iA7NEEu3BObNHAQ371VQ4uJQaZOysxPAH/RFHDHRtDa6R/J
  F6ca8z28mliQdZxFpyrqKgPwjrsthZ4BApUnHZ6dm9I5ATnr4m4jPQefMeSgGLYD
  I3Mk82COdct8ZNk108bOQjSAl+CPlARb53pItOZm21PL1lVwzcq1IXvUjJYjEOSA
  6SccakqFhF8cgQ==
  =A56Z
  -----END PGP MESSAGE-----
  </code></pre>
  
  <p><strong>6)</strong> When I try to decrypt the message I get two "gpg: [don't know]: invalid packet"-messages and the
  decryption fails:</p>
  
  <pre><code>$ gpg -vv --decrypt /tmp/ct.asc
  gpg: armor: BEGIN PGP MESSAGE
  Version: BCPG v@RELEASE_NAME@
  :pubkey enc packet: version 3, algo 1, keyid 46B51E4921B41E21
      data: [2046 bits]
  gpg: armor header:
  gpg: public key is 21B41E21
  gpg: using subkey 21B41E21 instead of primary key 79CC322A
  
  You need a passphrase to unlock the secret key for
  user: "Foo Bar (Test Key) &lt;foo@bar.com&gt;"
  gpg: using subkey 21B41E21 instead of primary key 79CC322A
  2048-bit RSA key, ID 21B41E21, created 2017-08-17 (main key ID 79CC322A)
  
  gpg: no running gpg-agent - starting one
  gpg: public key encrypted data: good DEK
  :encrypted data packet:
      length: 57
      mdc_method: 2
  gpg: encrypted with 2048-bit RSA key, ID 21B41E21, created 2017-08-17
        "Foo Bar (Test Key) &lt;foo@bar.com&gt;"
  gpg: AES256 encrypted data
  gpg: [don't know]: invalid packet (ctb=39)
  gpg: decryption okay
  gpg: [don't know]: invalid packet (ctb=44)
  $
  </code></pre>