diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
6 files changed, 93 insertions, 81 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 84f0c41cf..696f79cd7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -39,10 +39,12 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; +import android.widget.Toast; import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; +import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.Constants; @@ -287,34 +289,16 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener Log.d(Constants.TAG, "uri: " + mDataUri); try { - // get master key id using row id - long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri); - finallyEdit(masterKeyId); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - } - } - } - - @SuppressWarnings("unchecked") - private void finallyEdit(final long masterKeyId) { - if (masterKeyId != 0) { - PGPSecretKey masterKey = null; - try { - mKeyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); + Uri secretUri = KeychainContract.KeyRingData.buildSecretKeyRingUri(mDataUri); + mKeyRing = (PGPSecretKeyRing) ProviderHelper.getPGPKeyRing(this, secretUri); - masterKey = mKeyRing.getSecretKey(); + PGPSecretKey masterKey = mKeyRing.getSecretKey(); mMasterCanSign = PgpKeyHelper.isCertificationKey(mKeyRing.getSecretKey()); for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(mKeyRing.getSecretKeys())) { mKeys.add(key); mKeysUsages.add(-1); // get usage when view is created } - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId); - AppMsg.makeText(this, R.string.error_no_secret_key_found, AppMsg.STYLE_ALERT).show(); - // TODO - } - if (masterKey != null) { + boolean isSet = false; for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) { Log.d(Constants.TAG, "Added userId " + userId); @@ -327,17 +311,23 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener } mUserIds.add(userId); } - } - } - mCurrentPassphrase = ""; - buildLayout(false); + buildLayout(false); + + mCurrentPassphrase = ""; + mIsPassphraseSet = PassphraseCacheService.hasPassphrase(mKeyRing); + if (!mIsPassphraseSet) { + // check "no passphrase" checkbox and remove button + mNoPassphrase.setChecked(true); + mChangePassphrase.setVisibility(View.GONE); + } + + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e); + Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show(); + finish(); + } - mIsPassphraseSet = PassphraseCacheService.hasPassphrase(this, masterKeyId); - if (!mIsPassphraseSet) { - // check "no passphrase" checkbox and remove button - mNoPassphrase.setChecked(true); - mChangePassphrase.setVisibility(View.GONE); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 2ec4dd89e..a99c9eca8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -165,10 +165,11 @@ public class EncryptAsymmetricFragment extends Fragment { if (preselectedEncryptionKeyIds != null) { Vector<Long> goodIds = new Vector<Long>(); for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { - // TODO check for available encrypt keys... is this even relevant? + // TODO One query per selected key?! wtf try { long id = ProviderHelper.getMasterKeyId(getActivity(), - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(preselectedEncryptionKeyIds[i])) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( + Long.toString(preselectedEncryptionKeyIds[i])) ); goodIds.add(id); } catch (ProviderHelper.NotFoundException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index dceb9a0fc..ca26cac1c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -219,12 +219,8 @@ public class ViewKeyActivity extends ActionBarActivity { } else { // get public keyring as ascii armored string try { - long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); - - ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - this, new long[]{masterKeyId}); - - content = keyringArmored.get(0); + Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri); + content = ProviderHelper.getKeyRingAsArmoredString(this, uri); // Android will fail with android.os.TransactionTooLargeException if key is too big // see http://www.lonestarprod.com/?p=34 @@ -233,8 +229,12 @@ public class ViewKeyActivity extends ActionBarActivity { AppMsg.STYLE_ALERT).show(); return; } + } catch (IOException e) { + Log.e(Constants.TAG, "error processing key!", e); + AppMsg.makeText(this, R.string.error_invalid_data, AppMsg.STYLE_ALERT).show(); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); + AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); } } @@ -259,16 +259,18 @@ public class ViewKeyActivity extends ActionBarActivity { private void copyToClipboard(Uri dataUri) { // get public keyring as ascii armored string try { - long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); - - ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - this, new long[]{masterKeyId}); + Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri); + String keyringArmored = ProviderHelper.getKeyRingAsArmoredString(this, uri); - ClipboardReflection.copyToClipboard(this, keyringArmored.get(0)); + ClipboardReflection.copyToClipboard(this, keyringArmored); AppMsg.makeText(this, R.string.key_copied_to_clipboard, AppMsg.STYLE_INFO) .show(); + } catch (IOException e) { + Log.e(Constants.TAG, "error processing key!", e); + AppMsg.makeText(this, R.string.error_key_processing, AppMsg.STYLE_ALERT).show(); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); + AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index a7543d194..386342a48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -331,11 +331,8 @@ public class ViewKeyMainFragment extends Fragment implements } private void encryptToContact(Uri dataUri) { - // TODO preselect from uri? should be feasible without trivial query try { - long keyId = ProviderHelper.getMasterKeyId(getActivity(), - KeyRingData.buildPublicKeyRingUri(dataUri)); - + long keyId = ProviderHelper.extractOrGetMasterKeyId(getActivity(), dataUri); long[] encryptionKeyIds = new long[]{ keyId }; Intent intent = new Intent(getActivity(), EncryptActivity.class); intent.setAction(EncryptActivity.ACTION_ENCRYPT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java index 5631d40ea..44bde963e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java @@ -21,9 +21,12 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.SparseArray; +import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -46,31 +49,19 @@ public class ImportKeysListEntry implements Serializable, Parcelable { public int bitStrength; public String algorithm; public boolean secretKey; + public String mPrimaryUserId; private boolean mSelected; private byte[] mBytes = new byte[]{}; - public ImportKeysListEntry(ImportKeysListEntry b) { - this.userIds = b.userIds; - this.keyId = b.keyId; - this.revoked = b.revoked; - this.date = b.date; - this.fingerPrintHex = b.fingerPrintHex; - this.keyIdHex = b.keyIdHex; - this.bitStrength = b.bitStrength; - this.algorithm = b.algorithm; - this.secretKey = b.secretKey; - this.mSelected = b.mSelected; - this.mBytes = b.mBytes; - } - public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mPrimaryUserId); dest.writeStringList(userIds); dest.writeLong(keyId); dest.writeByte((byte) (revoked ? 1 : 0)); @@ -88,6 +79,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() { public ImportKeysListEntry createFromParcel(final Parcel source) { ImportKeysListEntry vr = new ImportKeysListEntry(); + vr.mPrimaryUserId = source.readString(); vr.userIds = new ArrayList<String>(); source.readStringList(vr.userIds); vr.keyId = source.readLong(); @@ -198,6 +190,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable { this.userIds = userIds; } + public String getPrimaryUserId() { + return mPrimaryUserId; + } + + public void setPrimaryUserId(String uid) { + mPrimaryUserId = uid; + } + /** * Constructor for later querying from keyserver */ @@ -229,20 +229,39 @@ public class ImportKeysListEntry implements Serializable, Parcelable { } else { secretKey = false; } + PGPPublicKey key = pgpKeyRing.getPublicKey(); userIds = new ArrayList<String>(); - for (String userId : new IterableIterator<String>(pgpKeyRing.getPublicKey().getUserIDs())) { + for (String userId : new IterableIterator<String>(key.getUserIDs())) { userIds.add(userId); + for(PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignaturesForID(userId))) { + if(sig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.PRIMARY_USER_ID)) { + try { + // make sure it's actually valid + sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME), key); + if (sig.verifyCertification(userId, key)) { + mPrimaryUserId = userId; + } + } catch(Exception e) { + // nothing bad happens, the key is just not considered the primary key id + } + } + + } + } + // if there was no user id flagged as primary, use the first one + if(mPrimaryUserId == null) { + mPrimaryUserId = userIds.get(0); } - this.keyId = pgpKeyRing.getPublicKey().getKeyID(); + this.keyId = key.getKeyID(); this.keyIdHex = PgpKeyHelper.convertKeyIdToHex(keyId); - this.revoked = pgpKeyRing.getPublicKey().isRevoked(); - this.fingerPrintHex = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey() - .getFingerprint()); - this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength(); - final int algorithm = pgpKeyRing.getPublicKey().getAlgorithm(); + this.revoked = key.isRevoked(); + this.fingerPrintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); + this.bitStrength = key.getBitStrength(); + final int algorithm = key.getAlgorithm(); this.algorithm = getAlgorithmFromId(algorithm); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java index d2d21093e..7e9a3d800 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java @@ -28,14 +28,19 @@ import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; + +import com.devspark.appmsg.AppMsg; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.QrCodeUtils; +import java.io.IOException; import java.util.ArrayList; public class ShareQrCodeDialogFragment extends DialogFragment { @@ -77,7 +82,6 @@ public class ShareQrCodeDialogFragment extends DialogFragment { mFingerprintOnly = getArguments().getBoolean(ARG_FINGERPRINT_ONLY); AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); - alert.setTitle(R.string.share_qr_code_dialog_title); LayoutInflater inflater = activity.getLayoutInflater(); @@ -95,7 +99,8 @@ public class ShareQrCodeDialogFragment extends DialogFragment { getActivity(), KeyRings.buildUnifiedKeyRingUri(dataUri), KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); if(blob == null) { - // TODO error handling?! + Log.e(Constants.TAG, "key not found!"); + AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); return null; } @@ -106,20 +111,18 @@ public class ShareQrCodeDialogFragment extends DialogFragment { } else { mText.setText(R.string.share_qr_code_dialog_start); - // TODO works, but - long masterKeyId = 0; try { - masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); + Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri); + content = ProviderHelper.getKeyRingAsArmoredString(getActivity(), uri); + } catch (IOException e) { + Log.e(Constants.TAG, "error processing key!", e); + AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT).show(); + return null; } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); + AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); + return null; } - // get public keyring as ascii armored string - ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - getActivity(), new long[] { masterKeyId }); - - // TODO: binary? - - content = keyringArmored.get(0); // OnClickListener are set in onResume to prevent automatic dismissing of Dialogs // http://bit.ly/O5vfaR |