From d75ea3f9e5b891e2dced2bb7cc0700c35f5bb7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 4 Feb 2014 14:20:49 +0100 Subject: Certify not sign a key, added as button, does not belong to menu --- .../keychain/pgp/PgpKeyOperation.java | 10 +- .../keychain/service/KeychainIntentService.java | 15 +- .../keychain/ui/CertifyKeyActivity.java | 319 ++++++++++++++++++++ .../keychain/ui/ImportKeysActivity.java | 8 +- .../keychain/ui/ImportKeysQrCodeFragment.java | 2 +- .../keychain/ui/SignKeyActivity.java | 321 --------------------- .../keychain/ui/ViewKeyActivity.java | 45 +-- 7 files changed, 363 insertions(+), 357 deletions(-) create mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SignKeyActivity.java (limited to 'OpenPGP-Keychain/src/main/java') 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 9782d1ac2..7caee4048 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 @@ -405,7 +405,7 @@ public class PgpKeyOperation { updateProgress(R.string.progress_done, 100, 100); } - public PGPPublicKeyRing signKey(long masterKeyId, long pubKeyId, String passphrase) + public PGPPublicKeyRing certifyKey(long masterKeyId, long pubKeyId, String passphrase) throws PgpGeneralException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException { if (passphrase == null) { @@ -414,14 +414,14 @@ public class PgpKeyOperation { PGPPublicKeyRing pubring = ProviderHelper .getPGPPublicKeyRingByKeyId(mContext, pubKeyId); - PGPSecretKey signingKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId); - if (signingKey == null) { + PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId); + if (certificationKey == null) { throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed)); } PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); + PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor); if (signaturePrivateKey == null) { throw new PgpGeneralException( mContext.getString(R.string.error_could_not_extract_private_key)); @@ -429,7 +429,7 @@ public class PgpKeyOperation { // TODO: SHA256 fixed? JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - signingKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) + certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( 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 657d40a5a..ddb53736a 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 @@ -54,7 +54,6 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.util.HkpKeyServer; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; import android.app.IntentService; @@ -96,7 +95,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String ACTION_UPLOAD_KEYRING = Constants.INTENT_PREFIX + "UPLOAD_KEYRING"; public static final String ACTION_DOWNLOAD_AND_IMPORT_KEYS = Constants.INTENT_PREFIX + "QUERY_KEYRING"; - public static final String ACTION_SIGN_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; + public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; /* keys for data bundle */ @@ -163,8 +162,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String DOWNLOAD_KEY_LIST = "query_key_id"; // sign key - public static final String SIGN_KEY_MASTER_KEY_ID = "sign_key_master_key_id"; - public static final String SIGN_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; + public static final String CERTIFY_KEY_MASTER_KEY_ID = "sign_key_master_key_id"; + public static final String CERTIFY_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; /* * possible data keys as result send over messenger @@ -777,19 +776,19 @@ public class KeychainIntentService extends IntentService implements ProgressDial } catch (Exception e) { sendErrorToHandler(e); } - } else if (ACTION_SIGN_KEYRING.equals(action)) { + } else if (ACTION_CERTIFY_KEYRING.equals(action)) { try { /* Input */ - long masterKeyId = data.getLong(SIGN_KEY_MASTER_KEY_ID); - long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID); + long masterKeyId = data.getLong(CERTIFY_KEY_MASTER_KEY_ID); + long pubKeyId = data.getLong(CERTIFY_KEY_PUB_KEY_ID); /* Operation */ String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId); PgpKeyOperation keyOperation = new PgpKeyOperation(this, this); - PGPPublicKeyRing signedPubKeyRing = keyOperation.signKey(masterKeyId, pubKeyId, + PGPPublicKeyRing signedPubKeyRing = keyOperation.certifyKey(masterKeyId, pubKeyId, signaturePassPhrase); // store the signed key in our local cache 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 new file mode 100644 index 000000000..c60b1c2ed --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2011 Senecaso + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.ui; + +import java.util.Iterator; + +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.Preferences; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Log; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.Spinner; +import android.widget.Toast; + +import com.beardedhen.androidbootstrap.BootstrapButton; + +/** + * Signs the specified public key with the specified secret master key + */ +public class CertifyKeyActivity extends ActionBarActivity implements + SelectSecretKeyLayoutFragment.SelectSecretKeyCallback { + private BootstrapButton mSignButton; + private CheckBox mUploadKeyCheckbox; + private Spinner mSelectKeyserverSpinner; + + private SelectSecretKeyLayoutFragment mSelectKeyFragment; + + private Uri mDataUri; + private long mPubKeyId = 0; + private long mMasterKeyId = 0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.certify_key_activity); + + final ActionBar actionBar = getSupportActionBar(); + actionBar.setDisplayShowTitleEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(false); + actionBar.setHomeButtonEnabled(false); + + mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getSupportFragmentManager() + .findFragmentById(R.id.sign_key_select_key_fragment); + mSelectKeyFragment.setCallback(this); + mSelectKeyFragment.setFilterCertify(true); + + mSelectKeyserverSpinner = (Spinner) findViewById(R.id.sign_key_keyserver); + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_spinner_item, Preferences.getPreferences(this) + .getKeyServers()); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mSelectKeyserverSpinner.setAdapter(adapter); + + mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); + if (!mUploadKeyCheckbox.isChecked()) { + mSelectKeyserverSpinner.setEnabled(false); + } else { + mSelectKeyserverSpinner.setEnabled(true); + } + + mUploadKeyCheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (!isChecked) { + mSelectKeyserverSpinner.setEnabled(false); + } else { + mSelectKeyserverSpinner.setEnabled(true); + } + } + }); + + mSignButton = (BootstrapButton) findViewById(R.id.sign_key_sign_button); + mSignButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mPubKeyId != 0) { + if (mMasterKeyId == 0) { + mSelectKeyFragment.setError(getString(R.string.select_key_to_sign)); + } else { + initiateSigning(); + } + } + } + }); + + mDataUri = getIntent().getData(); + if (mDataUri == null) { + Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!"); + finish(); + return; + } + + PGPPublicKeyRing signKey = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, mDataUri); + + if (signKey != null) { + mPubKeyId = PgpKeyHelper.getMasterKey(signKey).getKeyID(); + } + if (mPubKeyId == 0) { + Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); + finish(); + return; + } + } + + private void showPassphraseDialog(final long secretKeyId) { + // Message is received after passphrase is cached + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + startSigning(); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + try { + PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, + messenger, secretKeyId); + + passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); + } catch (PgpGeneralException e) { + Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); + // send message to handler to start encryption directly + returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); + } + } + + /** + * handles the UI bits of the signing process on the UI thread + */ + private void initiateSigning() { + PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, mPubKeyId); + if (pubring != null) { + // if we have already signed this key, dont bother doing it again + boolean alreadySigned = false; + + @SuppressWarnings("unchecked") + Iterator itr = pubring.getPublicKey(mPubKeyId).getSignatures(); + while (itr.hasNext()) { + PGPSignature sig = itr.next(); + if (sig.getKeyID() == mMasterKeyId) { + alreadySigned = true; + break; + } + } + + if (!alreadySigned) { + /* + * get the user's passphrase for this key (if required) + */ + String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); + if (passphrase == null) { + showPassphraseDialog(mMasterKeyId); + // bail out; need to wait until the user has entered the passphrase before trying again + return; + } else { + startSigning(); + } + } else { + Toast.makeText(this, R.string.key_has_already_been_signed, Toast.LENGTH_SHORT) + .show(); + + setResult(RESULT_CANCELED); + finish(); + } + } + } + + /** + * kicks off the actual signing process on a background thread + */ + private void startSigning() { + // Send all information needed to service to sign key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_CERTIFY_KEYRING); + + // fill values for this action + Bundle data = new Bundle(); + + data.putLong(KeychainIntentService.CERTIFY_KEY_MASTER_KEY_ID, mMasterKeyId); + data.putLong(KeychainIntentService.CERTIFY_KEY_PUB_KEY_ID, mPubKeyId); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Message is received after signing is done in ApgService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, + R.string.progress_signing, ProgressDialog.STYLE_SPINNER) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + + Toast.makeText(CertifyKeyActivity.this, R.string.key_sign_success, + Toast.LENGTH_SHORT).show(); + + // check if we need to send the key to the server or not + if (mUploadKeyCheckbox.isChecked()) { + // upload the newly signed key to the key server + uploadKey(); + } else { + setResult(RESULT_OK); + finish(); + } + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + + private void uploadKey() { + // Send all information needed to service to upload key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING); + + // set data uri as path to keyring + intent.setData(mDataUri); + + // fill values for this action + Bundle data = new Bundle(); + + Spinner keyServer = (Spinner) findViewById(R.id.sign_key_keyserver); + String server = (String) keyServer.getSelectedItem(); + data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, server); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Message is received after uploading is done in ApgService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, + R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + Toast.makeText(CertifyKeyActivity.this, R.string.key_send_success, + Toast.LENGTH_SHORT).show(); + + setResult(RESULT_OK); + finish(); + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + + /** + * callback from select key fragment + */ + @Override + public void onKeySelected(long secretKeyId) { + mMasterKeyId = secretKeyId; + } +} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index dc3a07def..70f3c955a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2012-2014 Dominik Schürmann * Copyright (C) 2011 Senecaso * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -127,7 +127,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa /* Scanning a fingerprint directly with Barcode Scanner */ getSupportActionBar().setSelectedNavigationItem(0); loadFragment(ImportKeysQrCodeFragment.class, null, mNavigationStrings[0]); - loadFromFingerprintUri(dataUri); + loadFromFingerprintUri(savedInstanceState, dataUri); } else if (ACTION_IMPORT_KEY.equals(action)) { /* Keychain's own Actions */ getSupportActionBar().setSelectedNavigationItem(1); @@ -248,7 +248,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa ft.commit(); } - public void loadFromFingerprintUri(Uri dataUri) { + public void loadFromFingerprintUri(Bundle savedInstanceState, Uri dataUri) { String fingerprint = dataUri.toString().split(":")[1].toLowerCase(Locale.ENGLISH); Log.d(Constants.TAG, "fingerprint: " + fingerprint); @@ -267,7 +267,7 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa args.putString(ImportKeysServerFragment.ARG_QUERY, query); loadFragment(ImportKeysServerFragment.class, args, mNavigationStrings[0]); - startListFragment(null, null, null, query); + startListFragment(savedInstanceState, null, null, query); } public void loadCallback(byte[] importData, Uri dataUri, String serverQuery, String keyServer) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index 63727ad26..27628dad4 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -130,7 +130,7 @@ public class ImportKeysQrCodeFragment extends Fragment { } public void importFingerprint(Uri dataUri) { - mImportActivity.loadFromFingerprintUri(dataUri); + mImportActivity.loadFromFingerprintUri(null, dataUri); } private void importParts(String[] parts) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SignKeyActivity.java deleted file mode 100644 index d9fb294d5..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/SignKeyActivity.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * Copyright (C) 2011 Senecaso - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.ui; - -import java.util.Iterator; - -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.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import android.app.ProgressDialog; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.Spinner; -import android.widget.Toast; - -import com.beardedhen.androidbootstrap.BootstrapButton; - -/** - * Signs the specified public key with the specified secret master key - */ -public class SignKeyActivity extends ActionBarActivity implements - SelectSecretKeyLayoutFragment.SelectSecretKeyCallback { - private BootstrapButton mSignButton; - private CheckBox mUploadKeyCheckbox; - private Spinner mSelectKeyserverSpinner; - - private SelectSecretKeyLayoutFragment mSelectKeyFragment; - - private Uri mDataUri; - private long mPubKeyId = 0; - private long mMasterKeyId = 0; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.sign_key_activity); - - final ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayShowTitleEnabled(true); - actionBar.setDisplayHomeAsUpEnabled(false); - actionBar.setHomeButtonEnabled(false); - - mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getSupportFragmentManager() - .findFragmentById(R.id.sign_key_select_key_fragment); - mSelectKeyFragment.setCallback(this); - mSelectKeyFragment.setFilterCertify(true); - - mSelectKeyserverSpinner = (Spinner) findViewById(R.id.sign_key_keyserver); - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, Preferences.getPreferences(this) - .getKeyServers()); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mSelectKeyserverSpinner.setAdapter(adapter); - - mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); - if (!mUploadKeyCheckbox.isChecked()) { - mSelectKeyserverSpinner.setEnabled(false); - } else { - mSelectKeyserverSpinner.setEnabled(true); - } - - mUploadKeyCheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (!isChecked) { - mSelectKeyserverSpinner.setEnabled(false); - } else { - mSelectKeyserverSpinner.setEnabled(true); - } - } - }); - - mSignButton = (BootstrapButton) findViewById(R.id.sign_key_sign_button); - mSignButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (mPubKeyId != 0) { - if (mMasterKeyId == 0) { - mSelectKeyFragment.setError(getString(R.string.select_key_to_sign)); - } else { - initiateSigning(); - } - } - } - }); - - mDataUri = getIntent().getData(); - if (mDataUri == null) { - Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!"); - finish(); - return; - } - - PGPPublicKeyRing signKey = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, mDataUri); - - if (signKey != null) { - mPubKeyId = PgpKeyHelper.getMasterKey(signKey).getKeyID(); - } - if (mPubKeyId == 0) { - Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); - finish(); - return; - } - } - - private void showPassphraseDialog(final long secretKeyId) { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - startSigning(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - try { - PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, - messenger, secretKeyId); - - passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PgpGeneralException e) { - Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); - // send message to handler to start encryption directly - returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); - } - } - - /** - * handles the UI bits of the signing process on the UI thread - */ - private void initiateSigning() { - PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, mPubKeyId); - if (pubring != null) { - // if we have already signed this key, dont bother doing it again - boolean alreadySigned = false; - - @SuppressWarnings("unchecked") - Iterator itr = pubring.getPublicKey(mPubKeyId).getSignatures(); - while (itr.hasNext()) { - PGPSignature sig = itr.next(); - if (sig.getKeyID() == mMasterKeyId) { - alreadySigned = true; - break; - } - } - - if (!alreadySigned) { - /* - * get the user's passphrase for this key (if required) - */ - String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); - if (passphrase == null) { - showPassphraseDialog(mMasterKeyId); - return; // bail out; need to wait until the user has entered the passphrase - // before trying again - } else { - startSigning(); - } - } else { - Toast.makeText(this, R.string.key_has_already_been_signed, Toast.LENGTH_SHORT) - .show(); - - setResult(RESULT_CANCELED); - finish(); - } - } - } - - /** - * kicks off the actual signing process on a background thread - */ - private void startSigning() { - // Send all information needed to service to sign key in other thread - Intent intent = new Intent(this, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_SIGN_KEYRING); - - // fill values for this action - Bundle data = new Bundle(); - - data.putLong(KeychainIntentService.SIGN_KEY_MASTER_KEY_ID, mMasterKeyId); - data.putLong(KeychainIntentService.SIGN_KEY_PUB_KEY_ID, mPubKeyId); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after signing is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - R.string.progress_signing, ProgressDialog.STYLE_SPINNER) { - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - - Toast.makeText(SignKeyActivity.this, R.string.key_sign_success, - Toast.LENGTH_SHORT).show(); - - // check if we need to send the key to the server or not - if (mUploadKeyCheckbox.isChecked()) { - /* - * upload the newly signed key to the key server - */ - uploadKey(); - } else { - setResult(RESULT_OK); - finish(); - } - } - }; - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - - private void uploadKey() { - // Send all information needed to service to upload key in other thread - Intent intent = new Intent(this, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING); - - // set data uri as path to keyring - intent.setData(mDataUri); - - // fill values for this action - Bundle data = new Bundle(); - - Spinner keyServer = (Spinner) findViewById(R.id.sign_key_keyserver); - String server = (String) keyServer.getSelectedItem(); - data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, server); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after uploading is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Toast.makeText(SignKeyActivity.this, R.string.key_send_success, - Toast.LENGTH_SHORT).show(); - - setResult(RESULT_OK); - finish(); - } - }; - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - - /** - * callback from select key fragment - */ - @Override - public void onKeySelected(long secretKeyId) { - mMasterKeyId = secretKeyId; - } -} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 99d93fbbd..0bfc51e67 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -75,6 +75,7 @@ public class ViewKeyActivity extends ActionBarActivity implements private TextView mCreation; private TextView mFingerprint; private BootstrapButton mActionEncrypt; + private BootstrapButton mActionCertify; private ListView mUserIds; private ListView mKeys; @@ -91,6 +92,7 @@ public class ViewKeyActivity extends ActionBarActivity implements mExportHelper = new ExportHelper(this); + // let the actionbar look like Android's contact app getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setIcon(android.R.color.transparent); getSupportActionBar().setHomeButtonEnabled(true); @@ -105,9 +107,10 @@ public class ViewKeyActivity extends ActionBarActivity implements mCreation = (TextView) findViewById(R.id.creation); mExpiry = (TextView) findViewById(R.id.expiry); mFingerprint = (TextView) findViewById(R.id.fingerprint); - mActionEncrypt = (BootstrapButton) findViewById(R.id.action_encrypt); mUserIds = (ListView) findViewById(R.id.user_ids); mKeys = (ListView) findViewById(R.id.keys); + mActionEncrypt = (BootstrapButton) findViewById(R.id.action_encrypt); + mActionCertify = (BootstrapButton) findViewById(R.id.action_certify); loadData(getIntent()); } @@ -130,9 +133,6 @@ public class ViewKeyActivity extends ActionBarActivity implements case R.id.menu_key_view_update: updateFromKeyserver(mDataUri); return true; - case R.id.menu_key_view_sign: - signKey(mDataUri); - return true; case R.id.menu_key_view_export_keyserver: uploadToKeyserver(mDataUri); return true; @@ -196,19 +196,18 @@ public class ViewKeyActivity extends ActionBarActivity implements @Override public void onClick(View v) { - long keyId = ProviderHelper.getMasterKeyId(ViewKeyActivity.this, mDataUri); - - long[] encryptionKeyIds = new long[]{keyId}; - Intent intent = new Intent(ViewKeyActivity.this, EncryptActivity.class); - intent.setAction(EncryptActivity.ACTION_ENCRYPT); - intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); - // used instead of startActivity set actionbar based on callingPackage - startActivityForResult(intent, 0); + encryptToContact(mDataUri); } }); + mActionCertify.setOnClickListener(new OnClickListener() { - mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0); + @Override + public void onClick(View v) { + certifyKey(mDataUri); + } + }); + mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0); mUserIds.setAdapter(mUserIdsAdapter); // mUserIds.setEmptyView(findViewById(android.R.id.empty)); // mUserIds.setClickable(true); @@ -219,11 +218,10 @@ public class ViewKeyActivity extends ActionBarActivity implements // }); mKeysAdapter = new ViewKeyKeysAdapter(this, null, 0); - mKeys.setAdapter(mKeysAdapter); - // Prepare the loader. Either re-connect with an existing one, - // or start a new one. + // Prepare the loaders. Either re-connect with an existing ones, + // or start new ones. getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this); getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this); @@ -405,8 +403,19 @@ public class ViewKeyActivity extends ActionBarActivity implements startActivityForResult(queryIntent, Id.request.look_up_key_id); } - private void signKey(Uri dataUri) { - Intent signIntent = new Intent(this, SignKeyActivity.class); + private void encryptToContact(Uri dataUri) { + long keyId = ProviderHelper.getMasterKeyId(ViewKeyActivity.this, dataUri); + + long[] encryptionKeyIds = new long[]{keyId}; + Intent intent = new Intent(ViewKeyActivity.this, EncryptActivity.class); + intent.setAction(EncryptActivity.ACTION_ENCRYPT); + intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); + // used instead of startActivity set actionbar based on callingPackage + startActivityForResult(intent, 0); + } + + private void certifyKey(Uri dataUri) { + Intent signIntent = new Intent(this, CertifyKeyActivity.class); signIntent.setData(dataUri); startActivity(signIntent); } -- cgit v1.2.3