From 95be228b474c31a47743e84cf2abc1dff1d63079 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 15 Mar 2014 18:12:44 +0100 Subject: [PATCH] certify: sign individual UIDs direct signing of pubkeys is out for now. not sure how this should be handled, but it's trivial to re-add so leaving this up for discussion for now. --- .../keychain/pgp/PgpKeyOperation.java | 20 +++++++++++++++---- .../service/KeychainIntentService.java | 4 ++-- .../keychain/ui/CertifyKeyActivity.java | 19 ++++++++++++------ 3 files changed, 31 insertions(+), 12 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 fe09ea525..78e48b4ab 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 @@ -408,7 +408,16 @@ public class PgpKeyOperation { 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 userIds, String passphrase) throws PgpGeneralException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException { if (passphrase == null) { @@ -437,7 +446,7 @@ public class PgpKeyOperation { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); - signatureGenerator.init(PGPSignature.DIRECT_KEY, signaturePrivateKey); + signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, signaturePrivateKey); } { // supply signatureGenerator with a SubpacketVector @@ -449,8 +458,11 @@ public class PgpKeyOperation { // fetch public key ring, add the certification and return it PGPPublicKeyRing pubring = ProviderHelper .getPGPPublicKeyRingByKeyId(mContext, pubKeyId); - PGPPublicKey signedKey = PGPPublicKey.addCertification(pubring.getPublicKey(pubKeyId), - signatureGenerator.generate()); + PGPPublicKey signedKey = pubring.getPublicKey(pubKeyId); + for(String userId : new IterableIterator(userIds.iterator())) { + PGPSignature sig = signatureGenerator.generateCertification(userId, signedKey); + signedKey = PGPPublicKey.addCertification(signedKey, userId, sig); + } pubring = PGPPublicKeyRing.insertPublicKey(pubring, signedKey); return pubring; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index eb2367061..506ff2735 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -805,7 +805,7 @@ public class KeychainIntentService extends IntentService /* Input */ long masterKeyId = data.getLong(CERTIFY_KEY_MASTER_KEY_ID); long pubKeyId = data.getLong(CERTIFY_KEY_PUB_KEY_ID); - // String[] userIds = data.getStringArray(CERTIFY_KEY_PUB_KEY_ID); + ArrayList userIds = data.getStringArrayList(CERTIFY_KEY_UIDS); /* Operation */ String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this, @@ -813,7 +813,7 @@ public class KeychainIntentService extends IntentService PgpKeyOperation keyOperation = new PgpKeyOperation(this, this); PGPPublicKeyRing signedPubKeyRing = keyOperation.certifyKey(masterKeyId, pubKeyId, - signaturePassPhrase); + userIds, signaturePassPhrase); // store the signed key in our local cache PgpImportExport pgpImportExport = new PgpImportExport(this, null); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 3590baa76..d8df5ced3 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -30,14 +30,12 @@ import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; -import android.text.format.DateFormat; import android.view.View; import android.view.View.OnClickListener; import android.widget.*; import android.widget.CompoundButton.OnCheckedChangeListener; import com.beardedhen.androidbootstrap.BootstrapButton; import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSignature; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.OtherHelper; @@ -53,8 +51,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.util.Date; -import java.util.Iterator; +import java.util.ArrayList; /** * Signs the specified public key with the specified secret master key @@ -267,6 +264,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements // if we have already signed this key, dont bother doing it again boolean alreadySigned = false; + /* todo: reconsider this at a later point when certs are in the db @SuppressWarnings("unchecked") Iterator itr = pubring.getPublicKey(mPubKeyId).getSignatures(); while (itr.hasNext()) { @@ -276,6 +274,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements break; } } + */ if (!alreadySigned) { /* @@ -303,6 +302,15 @@ public class CertifyKeyActivity extends ActionBarActivity implements * kicks off the actual signing process on a background thread */ private void startSigning() { + + // Bail out if there is not at least one user id selected + ArrayList userIds = mUserIdsAdapter.getSelectedUserIds(); + if(userIds.isEmpty()) { + Toast.makeText(CertifyKeyActivity.this, "No User IDs to sign selected!", + Toast.LENGTH_SHORT).show(); + return; + } + // Send all information needed to service to sign key in other thread Intent intent = new Intent(this, KeychainIntentService.class); @@ -313,8 +321,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements data.putLong(KeychainIntentService.CERTIFY_KEY_MASTER_KEY_ID, mMasterKeyId); data.putLong(KeychainIntentService.CERTIFY_KEY_PUB_KEY_ID, mPubKeyId); - data.putStringArray(KeychainIntentService.CERTIFY_KEY_UIDS, - (String[]) mUserIdsAdapter.getSelectedUserIds().toArray()); + data.putStringArrayList(KeychainIntentService.CERTIFY_KEY_UIDS, userIds); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);