aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-03-18 14:43:20 +0100
committerDominik Schürmann <dominik@dominikschuermann.de>2014-03-18 14:43:20 +0100
commit711a51f7fc72c4c13ea63bd11f7aa67a21a3307c (patch)
tree56d72b6812fc9ddb301bd9921b69823575f6f52f /OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
parent30644b5c4f72f828ecead09fc7e2d5d4ae8e91db (diff)
parent87004fd0ca3a5178fba3050599a445ba9c64662c (diff)
downloadopen-keychain-711a51f7fc72c4c13ea63bd11f7aa67a21a3307c.tar.gz
open-keychain-711a51f7fc72c4c13ea63bd11f7aa67a21a3307c.tar.bz2
open-keychain-711a51f7fc72c4c13ea63bd11f7aa67a21a3307c.zip
Merge pull request #430 from Valodim/certify
Revamp certify dialogue
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java334
1 files changed, 209 insertions, 125 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index c7ec02d7d..40a0b72ce 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Primes;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
@@ -46,6 +47,8 @@ import java.security.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.List;
import java.util.TimeZone;
public class PgpKeyOperation {
@@ -198,7 +201,7 @@ public class PgpKeyOperation {
public void buildSecretKey(ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
ArrayList<Integer> keysUsages, ArrayList<GregorianCalendar> keysExpiryDates,
- long masterKeyId, String oldPassPhrase,
+ PGPPublicKey oldPublicKey, String oldPassPhrase,
String newPassPhrase) throws PgpGeneralException, NoSuchProviderException,
PGPException, NoSuchAlgorithmException, SignatureException, IOException {
@@ -215,131 +218,166 @@ public class PgpKeyOperation {
updateProgress(R.string.progress_preparing_master_key, 10, 100);
- int usageId = keysUsages.get(0);
- boolean canSign =
- (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
- boolean canEncrypt =
- (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
-
- String mainUserId = userIds.get(0);
+ // prepare keyring generator with given master public and secret key
+ PGPKeyRingGenerator keyGen;
+ PGPPublicKey masterPublicKey; {
+
+ String mainUserId = userIds.get(0);
+
+ // prepare the master key pair
+ PGPKeyPair masterKeyPair; {
+
+ PGPSecretKey masterKey = keys.get(0);
+
+ // this removes all userIds and certifications previously attached to the masterPublicKey
+ PGPPublicKey tmpKey = masterKey.getPublicKey();
+ masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
+ tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
+
+ // already done by code above:
+ // PGPPublicKey masterPublicKey = masterKey.getPublicKey();
+ // // Somehow, the PGPPublicKey already has an empty certification attached to it when the
+ // // keyRing is generated the first time, we remove that when it exists, before adding the
+ // new
+ // // ones
+ // PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
+ // "");
+ // if (masterPublicKeyRmCert != null) {
+ // masterPublicKey = masterPublicKeyRmCert;
+ // }
+
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
+ PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
+
+ updateProgress(R.string.progress_certifying_master_key, 20, 100);
+
+ // re-add old certificates, or create new ones for new uids
+ for (String userId : userIds) {
+ // re-add certs for this uid, take a note if self-signed cert is in there
+ boolean foundSelfSign = false;
+ Iterator<PGPSignature> it = tmpKey.getSignaturesForID(userId);
+ if(it != null) for(PGPSignature sig : new IterableIterator<PGPSignature>(it)) {
+ if(sig.getKeyID() == masterPublicKey.getKeyID()) {
+ // already have a self sign? skip this other one, then.
+ // note: PGPKeyRingGenerator adds one cert for the main user id, which
+ // will lead to duplicates. unfortunately, if we add any other here
+ // first, that will change the main user id order...
+ if(foundSelfSign)
+ continue;
+ foundSelfSign = true;
+ }
+ Log.d(Constants.TAG, "adding old sig for " + userId + " from "
+ + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()));
+ masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, sig);
+ }
+
+ // there was an old self-signed certificate for this uid
+ if(foundSelfSign)
+ continue;
+
+ Log.d(Constants.TAG, "generating self-signed cert for " + userId);
+
+ PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
+ masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
+
+ sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
+
+ PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
+
+ masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
+ }
- PGPSecretKey masterKey = keys.get(0);
+ masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
+ }
- // this removes all userIds and certifications previously attached to the masterPublicKey
- PGPPublicKey tmpKey = masterKey.getPublicKey();
- PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
- tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
+ PGPSignatureSubpacketGenerator hashedPacketsGen;
+ PGPSignatureSubpacketGenerator unhashedPacketsGen; {
- // already done by code above:
- // PGPPublicKey masterPublicKey = masterKey.getPublicKey();
- // // Somehow, the PGPPublicKey already has an empty certification attached to it when the
- // // keyRing is generated the first time, we remove that when it exists, before adding the
- // new
- // // ones
- // PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
- // "");
- // if (masterPublicKeyRmCert != null) {
- // masterPublicKey = masterPublicKeyRmCert;
- // }
+ hashedPacketsGen = new PGPSignatureSubpacketGenerator();
+ unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
- PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
+ int usageId = keysUsages.get(0);
+ boolean canEncrypt =
+ (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
- updateProgress(R.string.progress_certifying_master_key, 20, 100);
+ int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
+ if (canEncrypt) {
+ keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
+ }
+ hashedPacketsGen.setKeyFlags(true, keyFlags);
+
+ hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
+ hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
+ hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
+
+ if (keysExpiryDates.get(0) != null) {
+ GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ creationDate.setTime(masterPublicKey.getCreationTime());
+ GregorianCalendar expiryDate = keysExpiryDates.get(0);
+ //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
+ //here we purposefully ignore partial days in each date - long type has no fractional part!
+ long numDays =
+ (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
+ if (numDays <= 0) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_expiry_must_come_after_creation));
+ }
+ hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
+ } else {
+ //do this explicitly, although since we're rebuilding,
+ hashedPacketsGen.setKeyExpirationTime(false, 0);
+ //this happens anyway
+ }
+ }
- // TODO: if we are editing a key, keep old certs, don't remake certs we don't have to.
+ updateProgress(R.string.progress_building_master_key, 30, 100);
- for (String userId : userIds) {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
+ // define hashing and signing algos
+ PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
+ HashAlgorithmTags.SHA1);
+ PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
+ masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
- sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
+ // Build key encrypter based on passphrase
+ PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
+ PGPEncryptedData.CAST5, sha1Calc)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ newPassPhrase.toCharArray());
- PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
+ keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
+ masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
+ unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
- masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
}
- PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
-
- PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
- PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
-
- int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
- if (canEncrypt) {
- keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
- }
- hashedPacketsGen.setKeyFlags(true, keyFlags);
-
- hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
- hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
- hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
-
- if (keysExpiryDates.get(0) != null) {
- GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
- creationDate.setTime(masterPublicKey.getCreationTime());
- GregorianCalendar expiryDate = keysExpiryDates.get(0);
- //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
- //here we purposefully ignore partial days in each date - long type has no fractional part!
- long numDays =
- (expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
- if (numDays <= 0) {
- throw new PgpGeneralException(
- mContext.getString(R.string.error_expiry_must_come_after_creation));
- }
- hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
- } else {
- //do this explicitly, although since we're rebuilding,
- hashedPacketsGen.setKeyExpirationTime(false, 0);
- //this happens anyway
- }
-
- updateProgress(R.string.progress_building_master_key, 30, 100);
-
- // define hashing and signing algos
- PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
- HashAlgorithmTags.SHA1);
- PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
- masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
-
- // Build key encrypter based on passphrase
- PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
- PGPEncryptedData.CAST5, sha1Calc)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassPhrase.toCharArray());
-
- PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
- masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
- unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
-
updateProgress(R.string.progress_adding_sub_keys, 40, 100);
for (int i = 1; i < keys.size(); ++i) {
- updateProgress(40 + 50 * (i - 1) / (keys.size() - 1), 100);
+ updateProgress(40 + 40 * (i - 1) / (keys.size() - 1), 100);
PGPSecretKey subKey = keys.get(i);
PGPPublicKey subPublicKey = subKey.getPublicKey();
- PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
oldPassPhrase.toCharArray());
- PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
+ PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor);
// TODO: now used without algorithm and creation time?! (APG 1)
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey, subPrivateKey);
- hashedPacketsGen = new PGPSignatureSubpacketGenerator();
- unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
+ PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
+ PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
- keyFlags = 0;
+ int keyFlags = 0;
- usageId = keysUsages.get(i);
- canSign =
+ int usageId = keysUsages.get(i);
+ boolean canSign =
(usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
- canEncrypt =
+ boolean canEncrypt =
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
if (canSign) {
Date todayDate = new Date(); //both sig times the same
@@ -388,53 +426,99 @@ public class PgpKeyOperation {
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
+ updateProgress(R.string.progress_re_adding_certs, 80, 100);
+
+ // re-add certificates from old public key
+ // TODO: this only takes care of user id certificates, what about others?
+ PGPPublicKey pubkey = publicKeyRing.getPublicKey();
+ for(String uid : new IterableIterator<String>(pubkey.getUserIDs())) {
+ for(PGPSignature sig : new IterableIterator<PGPSignature>(oldPublicKey.getSignaturesForID(uid), true)) {
+ // but skip self certificates
+ if(sig.getKeyID() == pubkey.getKeyID())
+ continue;
+ pubkey = PGPPublicKey.addCertification(pubkey, uid, sig);
+ }
+ }
+ publicKeyRing = PGPPublicKeyRing.insertPublicKey(publicKeyRing, pubkey);
+
updateProgress(R.string.progress_saving_key_ring, 90, 100);
+ /* additional handy debug info
+ Log.d(Constants.TAG, " ------- in private key -------");
+ for(String uid : new IterableIterator<String>(secretKeyRing.getPublicKey().getUserIDs())) {
+ for(PGPSignature sig : new IterableIterator<PGPSignature>(secretKeyRing.getPublicKey().getSignaturesForID(uid))) {
+ Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
+ }
+ }
+ Log.d(Constants.TAG, " ------- in public key -------");
+ for(String uid : new IterableIterator<String>(publicKeyRing.getPublicKey().getUserIDs())) {
+ for(PGPSignature sig : new IterableIterator<PGPSignature>(publicKeyRing.getPublicKey().getSignaturesForID(uid))) {
+ Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
+ }
+ }
+ */
+
ProviderHelper.saveKeyRing(mContext, secretKeyRing);
ProviderHelper.saveKeyRing(mContext, publicKeyRing);
updateProgress(R.string.progress_done, 100, 100);
}
- public PGPPublicKeyRing certifyKey(long masterKeyId, long pubKeyId, String passphrase)
+ /**
+ * Certify the given pubkeyid with the given masterkeyid.
+ *
+ * @param masterKeyId Certifying key, must be available as secret key
+ * @param pubKeyId ID of public key to certify
+ * @param userIds User IDs to certify, must not be null or empty
+ * @param passphrase Passphrase of the secret key
+ * @return A keyring with added certifications
+ */
+ public PGPPublicKeyRing certifyKey(long masterKeyId, long pubKeyId, List<String> userIds, String passphrase)
throws PgpGeneralException, NoSuchAlgorithmException, NoSuchProviderException,
PGPException, SignatureException {
if (passphrase == null) {
throw new PgpGeneralException("Unable to obtain passphrase");
} else {
- PGPPublicKeyRing pubring = ProviderHelper
- .getPGPPublicKeyRingByKeyId(mContext, pubKeyId);
- PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId);
- if (certificationKey == null) {
- throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
- }
+ // create a signatureGenerator from the supplied masterKeyId and passphrase
+ PGPSignatureGenerator signatureGenerator; {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
- PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor);
- if (signaturePrivateKey == null) {
- throw new PgpGeneralException(
- mContext.getString(R.string.error_could_not_extract_private_key));
- }
-
- // TODO: SHA256 fixed?
- JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
- certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId);
+ if (certificationKey == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
+ }
- PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
- contentSignerBuilder);
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor);
+ if (signaturePrivateKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_could_not_extract_private_key));
+ }
- signatureGenerator.init(PGPSignature.DIRECT_KEY, signaturePrivateKey);
+ // TODO: SHA256 fixed?
+ JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
+ certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, signaturePrivateKey);
+ }
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
+ { // supply signatureGenerator with a SubpacketVector
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ PGPSignatureSubpacketVector packetVector = spGen.generate();
+ signatureGenerator.setHashedSubpackets(packetVector);
+ }
- PGPPublicKey signedKey = PGPPublicKey.addCertification(pubring.getPublicKey(pubKeyId),
- signatureGenerator.generate());
+ // fetch public key ring, add the certification and return it
+ PGPPublicKeyRing pubring = ProviderHelper
+ .getPGPPublicKeyRingByKeyId(mContext, pubKeyId);
+ PGPPublicKey signedKey = pubring.getPublicKey(pubKeyId);
+ for(String userId : new IterableIterator<String>(userIds.iterator())) {
+ PGPSignature sig = signatureGenerator.generateCertification(userId, signedKey);
+ signedKey = PGPPublicKey.addCertification(signedKey, userId, sig);
+ }
pubring = PGPPublicKeyRing.insertPublicKey(pubring, signedKey);
return pubring;