title: Bouncycastle openpgpg: How to create a PGP keypair with two user ids?
body: <p>using the command line gnupg i can create a key ring with a RSA key for "John Doe &lt;john@doe.com&gt;". I can also add another user with uid "Jane Doe &lt;jane@doe.com&gt;" using <code>--edit-key</code> and <code>adduid</code>. The resulting secring.gpg then  looks like this:</p>
  
  <pre><code>$ gpg -vv secring.gpg
  :secret key packet:
          version 4, algo 1, created 1380898817, expires 0
          skey[0]: [2048 bits]
          skey[1]: [17 bits]
          iter+salt S2K, algo: 9, SHA1 protection, hash: 2, salt: 3825c4409323d7b0
          protect count: 65536 (96)
          protect IV:  ac f9 8d 4a b7 3a 5d 7c b2 3c 28 ff 82 6d 4c ef
          encrypted stuff follows
  :user ID packet: "John Doe &lt;john@doe.com&gt;"
  :signature packet: algo 1, keyid 9991E2282A9906C7
          version 4, created 1380898818, md5len 0, sigclass 0x13
          digest algo 2, begin of digest bd 01
          hashed subpkt 2 len 4 (sig created 2013-10-04)
          hashed subpkt 27 len 1 (key flags: 03)
          hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
          hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
          hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
          hashed subpkt 30 len 1 (features: 01)
          subpkt 16 len 8 (issuer key ID 9991E2282A9906C7)
          data: [2045 bits]
  :trust packet: flag=00 sigcache=00
  :user ID packet: "Jane Doe &lt;jane@doe.com&gt;"
  :signature packet: algo 1, keyid 9991E2282A9906C7
          version 4, created 1380899570, md5len 0, sigclass 0x13
          digest algo 2, begin of digest 2f 50
          hashed subpkt 2 len 4 (sig created 2013-10-04)
          hashed subpkt 27 len 1 (key flags: 03)
          hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
          hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
          hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
          hashed subpkt 30 len 1 (features: 01)
          hashed subpkt 23 len 1 (key server preferences: 80)
          subpkt 16 len 8 (issuer key ID 9991E2282A9906C7)
          data: [2047 bits]
  :trust packet: flag=00 sigcache=00
  sec  2048R/2A9906C7 2013-10-04 John Doe &lt;john@doe.com&gt;
  sig        2A9906C7 2013-10-04   [selfsig]
  uid                            Jane Doe &lt;jane@doe.com&gt;
  sig        2A9906C7 2013-10-04   [selfsig]
  </code></pre>
  
  <p>I'd like to create the same in Java, using Bouncycastle, starting from a java.security.KeyPair, i.e. with a signature like this:</p>
  
  <pre><code>public void createKeyRing(KeyPair keyPair, char[] pass, String[] ids)
  </code></pre>
  
  <p>where pass is the passphrase and <code>ids = new String[] {"John Doe &lt;john@doe.com&gt;", "Jane Doe &lt;jane@doe.com&gt;"}</code>. I followed the lines of <a href="http://bouncycastle-pgp-cookbook.blogspot.de/" rel="nofollow">this tutorial</a>, where the key part of the code is:</p>
  
  <pre><code>PGPKeyRingGenerator keyRingGen =
      new PGPKeyRingGenerator(
          PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign,
          id, sha1Calc, signhashgen.generate(), null,
          new BcPGPContentSignerBuilder(
              rsakp_sign.getPublicKey().getAlgorithm(),
              HashAlgorithmTags.SHA1),
          pske);
  
  // Add our encryption subkey, together with its signature.
  keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null);
  </code></pre>
  
  <p>where rsakp_sign and rsakp_enc are the RSA keypairs of the sign and encryption keys, respectively, and signhashgen and enchashgen are the generators for the subpackets that contain algorithm preferences and such.</p>
  
  <p>As long as i only create a key for John, all is well. But when i want to add Jane, i run into a problem: apparently i can not add a signhashgen-ified keypair for Jane using addSubKey. The first naive attempt goes like this:</p>
  
  <pre><code>PGPSignatureGenerator sGen = new PGPSignatureGenerator(
    new BcPGPContentSignerBuilder(PGPPublicKey.RSA_SIGN, PGPUtil.SHA1));
  sGen.init(PGPSignature.POSITIVE_CERTIFICATION, pgpPrivateKey);
  PGPSignature certification = sGen.generateCertification("Jane Doe &lt;jane@doe.com&gt;", pgpPublicKey);
  
  PGPPublicKey newKey = PGPPublicKey.addCertification(pgpPublicKey, "Jane Doe &lt;jane@doe.com&gt;", certification);
  
  keyRingGen.addSubKey(new PGPKeyPair(newKey, pgpPrivateKey), enchashgen.generate(), null);
  </code></pre>
  
  <p>and that just doesn't do anything, no additional entries show up in <code>gpg --vv meeththedoes.asc</code>.</p>
  
  <p>Alternatively, i can take John's keyring, extract the secret key, and then add Jane:</p>
  
  <pre><code>PGPSecretKeyRing keyRing = keyRingGen.generateSecretKeyRing();
  
  PGPSecretKey pgpSecretKey = keyRing.getSecretKey();
  BcPGPDigestCalculatorProvider calculatorProvider = new BcPGPDigestCalculatorProvider();
  BcPBESecretKeyDecryptorBuilder decryptor = new BcPBESecretKeyDecryptorBuilder(calculatorProvider);
  PGPPrivateKey pgpPrivateKey = pgpSecretKey.extractPrivateKey(decryptor.build(pass));    
  PGPPublicKey pgpPublicKey = pgpSecretKey.getPublicKey();
  
  PGPSignatureGenerator    sGen = new PGPSignatureGenerator(
    new BcPGPContentSignerBuilder(PGPPublicKey.RSA_SIGN, PGPUtil.SHA1));
  sGen.init(PGPSignature.POSITIVE_CERTIFICATION, pgpPrivateKey);
  PGPSignature certification = sGen.generateCertification("Jane Doe &lt;jane@doe.com&gt;", pgpPublicKey);
  
  PGPPublicKey newKey = PGPPublicKey.addCertification(pgpPublicKey, "Jane Doe &lt;jane@doe.com&gt;", certification);
  
  pgpSecretKey = PGPSecretKey.replacePublicKey(pgpSecretKey, newKey);
  </code></pre>
  
  <p>This kinda works, but in the resulting key ring John and Jane have different sets of subpackets:</p>
  
  <pre><code>$ gpg -vv meetthedoes.asc
  gpg: ASCII-Hülle: BEGIN PGP PRIVATE KEY BLOCK
  gpg: ASCII-Hülle: Version: BCPG v1.48
  :secret key packet:
          version 4, algo 3, created 1380908986, expires 0
          skey[0]: [2048 bits]
          skey[1]: [17 bits]
          iter+salt S2K, algo: 9, SHA1 protection, hash: 2, salt: 696d2d42bd6b727c
          protect count: 65536 (96)
          protect IV:  87 31 81 df 17 fa 74 c4 c3 35 39 26 98 c1 15 27
          encrypted stuff follows
  :user ID packet: "John Doe &lt;john@doe.com&gt;"
  :signature packet: algo 3, keyid 3A80073198CF2010
          version 4, created 1380908986, md5len 0, sigclass 0x13
          digest algo 2, begin of digest a5 c8
          hashed subpkt 2 len 4 (sig created 2013-10-04)
          hashed subpkt 27 len 1 (key flags: 03)
          hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
          hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
          hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
          hashed subpkt 30 len 1 (features: 01)
          subpkt 16 len 8 (issuer key ID 3A80073198CF2010)
          data: [2047 bits]
  :user ID packet: "Jane Doe &lt;jane@doe.com&gt;"
  :signature packet: algo 3, keyid 3A80073198CF2010
          version 4, created 1380908986, md5len 0, sigclass 0x13
          digest algo 2, begin of digest f6 e8
          hashed subpkt 2 len 4 (sig created 2013-10-04)
          subpkt 16 len 8 (issuer key ID 3A80073198CF2010)
          data: [2039 bits]
  sec  2048s/98CF2010 2013-10-04 John Doe &lt;john@doe.com&gt;
  sig        98CF2010 2013-10-04   [selfsig]
  uid                            Jane Doe &lt;jane@doe.com&gt;
  sig        98CF2010 2013-10-04   [selfsig]
  </code></pre>
  
  <p>which i probably don't want, right? In any case, the method seems wrong, too. Shouldn't i be able to instrument the generator completely first, and then have Bouncycastle generate the key ring file in one fell swoop? What am i doing wrong here?</p>