From b509c3ed399c07de02cbf777010cc4806db16cda Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 May 2015 23:05:58 +0200 Subject: fix fragment handling in ViewKeyActivity Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java --- .../keychain/ui/ViewKeyActivity.java | 40 +++++++--------------- 1 file changed, 12 insertions(+), 28 deletions(-) (limited to 'OpenKeychain/src/main') 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 5466c0b9a..7d57538b6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -274,9 +274,19 @@ public class ViewKeyActivity extends BaseNfcActivity implements result.createNotify(this).show(); } - startFragment(savedInstanceState, mDataUri); + // Fragments are stored, no need to recreate those + if (savedInstanceState != null) { + return; + } - if (savedInstanceState == null && getIntent().hasExtra(EXTRA_NFC_AID)) { + FragmentManager manager = getSupportFragmentManager(); + // Create an instance of the fragment + final ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri); + manager.beginTransaction() + .replace(R.id.view_key_fragment, frag) + .commit(); + + if (getIntent().hasExtra(EXTRA_NFC_AID)) { Intent intent = getIntent(); byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS); String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID); @@ -291,26 +301,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements setContentView(R.layout.view_key_activity); } - private void startFragment(Bundle savedInstanceState, Uri dataUri) { - // However, if we're being restored from a previous state, - // then we don't need to do anything and should return or else - // we could end up with overlapping fragments. - if (savedInstanceState != null) { - return; - } - - // Create an instance of the fragment - ViewKeyFragment frag = ViewKeyFragment.newInstance(dataUri); - - // Add the fragment to the 'fragment_container' FrameLayout - // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! - getSupportFragmentManager().beginTransaction() - .replace(R.id.view_key_fragment, frag) - .commitAllowingStateLoss(); - // do it immediately! - getSupportFragmentManager().executePendingTransactions(); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -435,12 +425,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements startActivityForResult(intent, 0); } - @Override - protected void onSaveInstanceState(Bundle outState) { - //Note:-Done due to the same weird crashes as for commitAllowingStateLoss() - //super.onSaveInstanceState(outState); - } - private void showQrCodeDialog() { Intent qrCodeIntent = new Intent(this, QrCodeViewActivity.class); -- cgit v1.2.3 From d06ae7f691e3bf1984cb79f94aa5a455c88f36f8 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 15 May 2015 01:04:25 +0200 Subject: yubikey: don't assume signing key is masterKeyId in ViewKeyActivity Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java --- .../ui/CreateKeyYubiKeyImportFragment.java | 10 ++- .../keychain/ui/ViewKeyActivity.java | 84 ++++++++++++---------- 2 files changed, 53 insertions(+), 41 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java index 4c7d1dfbd..f8d79d33b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java @@ -193,13 +193,19 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe ImportKeyResult result = returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); - if (!result.success()) { + long[] masterKeyIds = result.getImportedMasterKeyIds(); + + // TODO handle masterKeyIds.length != 1...? sorta outlandish scenario + + if (!result.success() || masterKeyIds.length == 0) { result.createNotify(getActivity()).show(); return; } Intent intent = new Intent(getActivity(), ViewKeyActivity.class); - intent.setData(KeyRings.buildGenericKeyRingUri(mNfcMasterKeyId)); + // use the imported masterKeyId, not the one from the yubikey, because + // that one might* just have been a subkey of the imported key + intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyIds[0])); intent.putExtra(ViewKeyActivity.EXTRA_DISPLAY_RESULT, result); intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, mNfcAid); intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, mNfcUserId); 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 7d57538b6..8c1d23d68 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -535,49 +535,54 @@ public class ViewKeyActivity extends BaseNfcActivity implements final String nfcUserId = nfcGetUserId(); final byte[] nfcAid = nfcGetAid(); - String fp = KeyFormattingUtils.convertFingerprintToHex(nfcFingerprints); - final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints); - - if (!mFingerprint.equals(fp)) { - try { - CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing(masterKeyId); - ring.getMasterKeyId(); - - Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG, - Style.WARN, new ActionListener() { - @Override - public void onAction() { - Intent intent = new Intent( - ViewKeyActivity.this, ViewKeyActivity.class); - intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints); - startActivity(intent); - finish(); - } - }, R.string.snack_yubikey_view).show(); - return; + long yubiKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints); + + try { - } catch (PgpKeyNotFoundException e) { - Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG, - Style.WARN, new ActionListener() { - @Override - public void onAction() { - Intent intent = new Intent( - ViewKeyActivity.this, CreateKeyActivity.class); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId); - intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints); - startActivity(intent); - finish(); - } - }, R.string.snack_yubikey_import).show(); + // if the yubikey matches a subkey in any key + CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(yubiKeyId)); + byte[] candidateFp = ring.getFingerprint(); + + // if the master key of that key matches this one, just show the yubikey dialog + if (KeyFormattingUtils.convertFingerprintToHex(candidateFp).equals(mFingerprint)) { + showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid); return; } - } - showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid); + // otherwise, offer to go to that key + final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(candidateFp); + Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG, + Style.WARN, new ActionListener() { + @Override + public void onAction() { + Intent intent = new Intent( + ViewKeyActivity.this, ViewKeyActivity.class); + intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints); + startActivity(intent); + finish(); + } + }, R.string.snack_yubikey_view).show(); + + // and if it's not found, offer import + } catch (PgpKeyNotFoundException e) { + Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG, + Style.WARN, new ActionListener() { + @Override + public void onAction() { + Intent intent = new Intent( + ViewKeyActivity.this, CreateKeyActivity.class); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId); + intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints); + startActivity(intent); + finish(); + } + }, R.string.snack_yubikey_import).show(); + } } @@ -794,6 +799,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements // old cursor once we return.) switch (loader.getId()) { case LOADER_ID_UNIFIED: { + if (data.moveToFirst()) { // get name, email, and comment from USER_ID KeyRing.UserId mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID)); -- cgit v1.2.3 From f6643962afdf980fe50740eb3c667bf280c15c56 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 May 2015 23:29:59 +0200 Subject: allow state loss when yubikey fragment is loaded --- .../main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main') 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 8c1d23d68..320ccee5d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -596,7 +596,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements manager.beginTransaction() .addToBackStack("yubikey") .replace(R.id.view_key_fragment, frag) - .commit(); + // if this is called while the activity wasn't resumed, just forget it happened + .commitAllowingStateLoss(); } private void encrypt(Uri dataUri, boolean text) { -- cgit v1.2.3 From 71818934ca04fe3e913b919105e5fa302c5c0d99 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 May 2015 23:59:04 +0200 Subject: pass masterKeyId to yubikey fragment --- .../org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 2 +- .../keychain/ui/ViewKeyYubiKeyFragment.java | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main') 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 320ccee5d..023483193 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -588,7 +588,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements public void showYubiKeyFragment(byte[] nfcFingerprints, String nfcUserId, byte[] nfcAid) { ViewKeyYubiKeyFragment frag = ViewKeyYubiKeyFragment.newInstance( - nfcFingerprints, nfcUserId, nfcAid); + mMasterKeyId, nfcFingerprints, nfcUserId, nfcAid); FragmentManager manager = getSupportFragmentManager(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java index 812874456..99ac73800 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java @@ -45,14 +45,15 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; public class ViewKeyYubiKeyFragment extends Fragment implements LoaderCallbacks { + public static final String ARG_MASTER_KEY_ID = "master_key_id"; public static final String ARG_FINGERPRINT = "fingerprint"; public static final String ARG_USER_ID = "user_id"; public static final String ARG_CARD_AID = "aid"; + private byte[][] mFingerprints; private String mUserId; private byte[] mCardAid; @@ -60,10 +61,12 @@ public class ViewKeyYubiKeyFragment extends Fragment private Button vButton; private TextView vStatus; - public static ViewKeyYubiKeyFragment newInstance(byte[] fingerprints, String userId, byte[] aid) { + public static ViewKeyYubiKeyFragment newInstance(long masterKeyId, + byte[] fingerprints, String userId, byte[] aid) { ViewKeyYubiKeyFragment frag = new ViewKeyYubiKeyFragment(); Bundle args = new Bundle(); + args.putLong(ARG_MASTER_KEY_ID, masterKeyId); args.putByteArray(ARG_FINGERPRINT, fingerprints); args.putString(ARG_USER_ID, userId); args.putByteArray(ARG_CARD_AID, aid); @@ -86,7 +89,7 @@ public class ViewKeyYubiKeyFragment extends Fragment mUserId = args.getString(ARG_USER_ID); mCardAid = args.getByteArray(ARG_CARD_AID); - mMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints[0]); + mMasterKeyId = args.getLong(ARG_MASTER_KEY_ID); getLoaderManager().initLoader(0, null, this); @@ -169,8 +172,8 @@ public class ViewKeyYubiKeyFragment extends Fragment Keys.HAS_SECRET, Keys.FINGERPRINT }; - private static final int INDEX_KEY_ID = 1; - private static final int INDEX_RANK = 2; + // private static final int INDEX_KEY_ID = 1; + // private static final int INDEX_RANK = 2; private static final int INDEX_HAS_SECRET = 3; private static final int INDEX_FINGERPRINT = 4; -- cgit v1.2.3 From 158263f2555eec0bb6e2b3738fa2edfbca71ae72 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 00:35:10 +0200 Subject: apply promote operation to specific subkeys present on yubikey only --- .../keychain/operations/PromoteKeyOperation.java | 31 ++++++++++++++++++++-- .../operations/results/OperationResult.java | 3 +++ .../keychain/pgp/CanonicalizedKeyRing.java | 7 ++++- .../keychain/pgp/CanonicalizedPublicKeyRing.java | 17 ++++++++++-- .../keychain/service/KeychainIntentService.java | 8 +++--- .../keychain/ui/ViewKeyYubiKeyFragment.java | 9 ++++++- OpenKeychain/src/main/res/values/strings.xml | 3 +++ 7 files changed, 69 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java index ef08b0b77..558756378 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java @@ -25,6 +25,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult; import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; @@ -34,6 +35,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ProgressScaler; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; /** An operation which promotes a public key ring to a secret one. @@ -50,7 +52,7 @@ public class PromoteKeyOperation extends BaseOperation { super(context, providerHelper, progressable, cancelled); } - public PromoteKeyResult execute(long masterKeyId, byte[] cardAid) { + public PromoteKeyResult execute(long masterKeyId, byte[] cardAid, long[] subKeyIds) { OperationLog log = new OperationLog(); log.add(LogType.MSG_PR, 0); @@ -65,8 +67,24 @@ public class PromoteKeyOperation extends BaseOperation { CanonicalizedPublicKeyRing pubRing = mProviderHelper.getCanonicalizedPublicKeyRing(masterKeyId); + if (subKeyIds == null) { + log.add(LogType.MSG_PR_ALL, 1); + } else { + // sort for binary search + for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) { + long subKeyId = key.getKeyId(); + if (naiveIndexOf(subKeyIds, subKeyId) != null) { + log.add(LogType.MSG_PR_SUBKEY_MATCH, 1, + KeyFormattingUtils.convertKeyIdToHex(subKeyId)); + } else { + log.add(LogType.MSG_PR_SUBKEY_NOMATCH, 1, + KeyFormattingUtils.convertKeyIdToHex(subKeyId)); + } + } + } + // create divert-to-card secret key from public key - promotedRing = pubRing.createDivertSecretRing(cardAid); + promotedRing = pubRing.createDivertSecretRing(cardAid, subKeyIds); } catch (NotFoundException e) { log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2); @@ -106,4 +124,13 @@ public class PromoteKeyOperation extends BaseOperation { } + static private Integer naiveIndexOf(long[] haystack, long needle) { + for (int i = 0; i < haystack.length; i++) { + if (needle == haystack[i]) { + return i; + } + } + return null; + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 094afd4a5..d39ab3695 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -558,8 +558,11 @@ public abstract class OperationResult implements Parcelable { // promote key MSG_PR (LogLevel.START, R.string.msg_pr), + MSG_PR_ALL (LogLevel.DEBUG, R.string.msg_pr_all), MSG_PR_ERROR_KEY_NOT_FOUND (LogLevel.ERROR, R.string.msg_pr_error_key_not_found), MSG_PR_FETCHING (LogLevel.DEBUG, R.string.msg_pr_fetching), + MSG_PR_SUBKEY_MATCH (LogLevel.DEBUG, R.string.msg_pr_subkey_match), + MSG_PR_SUBKEY_NOMATCH (LogLevel.WARN, R.string.msg_pr_subkey_nomatch), MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success), // messages used in UI code diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java index 4adacaf23..432ba23e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPPublicKey; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -127,7 +128,11 @@ public abstract class CanonicalizedKeyRing extends KeyRing { } public CanonicalizedPublicKey getPublicKey(long id) { - return new CanonicalizedPublicKey(this, getRing().getPublicKey(id)); + PGPPublicKey pubKey = getRing().getPublicKey(id); + if (pubKey == null) { + return null; + } + return new CanonicalizedPublicKey(this, pubKey); } public byte[] getEncoded() throws IOException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java index 8432b8f9f..68fd4a428 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java @@ -103,9 +103,22 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing { } /** Create a dummy secret ring from this key */ - public UncachedKeyRing createDivertSecretRing (byte[] cardAid) { + public UncachedKeyRing createDivertSecretRing (byte[] cardAid, long[] subKeyIds) { PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), cardAid); - return new UncachedKeyRing(secRing); + + if (subKeyIds == null) { + return new UncachedKeyRing(secRing); + } + + // if only specific subkeys should be promoted, construct a + // stripped dummy, then move divert-to-card keys over + PGPSecretKeyRing newRing = PGPSecretKeyRing.constructDummyFromPublic(getRing()); + for (long subKeyId : subKeyIds) { + newRing = PGPSecretKeyRing.insertSecretKey(newRing, secRing.getSecretKey(subKeyId)); + } + + return new UncachedKeyRing(newRing); + } } \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index e0509ac9b..71e149672 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -65,7 +65,6 @@ import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableFileCache; -import org.sufficientlysecure.keychain.util.Passphrase; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -185,6 +184,7 @@ public class KeychainIntentService extends IntentService implements Progressable // promote key public static final String PROMOTE_MASTER_KEY_ID = "promote_master_key_id"; public static final String PROMOTE_CARD_AID = "promote_card_aid"; + public static final String PROMOTE_SUBKEY_IDS = "promote_fingerprints"; // consolidate public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery"; @@ -476,10 +476,12 @@ public class KeychainIntentService extends IntentService implements Progressable // Input long keyRingId = data.getLong(PROMOTE_MASTER_KEY_ID); byte[] cardAid = data.getByteArray(PROMOTE_CARD_AID); + long[] subKeyIds = data.getLongArray(PROMOTE_SUBKEY_IDS); // Operation - PromoteKeyOperation op = new PromoteKeyOperation(this, providerHelper, this, mActionCanceled); - PromoteKeyResult result = op.execute(keyRingId, cardAid); + PromoteKeyOperation op = new PromoteKeyOperation( + this, providerHelper, this, mActionCanceled); + PromoteKeyResult result = op.execute(keyRingId, cardAid, subKeyIds); // Result sendMessageToHandler(MessageStatus.OKAY, result); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java index 99ac73800..ecd351965 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java @@ -45,6 +45,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; + public class ViewKeyYubiKeyFragment extends Fragment implements LoaderCallbacks { @@ -154,6 +156,11 @@ public class ViewKeyYubiKeyFragment extends Fragment Bundle data = new Bundle(); data.putLong(KeychainIntentService.PROMOTE_MASTER_KEY_ID, mMasterKeyId); data.putByteArray(KeychainIntentService.PROMOTE_CARD_AID, mCardAid); + long[] subKeyIds = new long[mFingerprints.length]; + for (int i = 0; i < subKeyIds.length; i++) { + subKeyIds[i] = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints[i]); + } + data.putLongArray(KeychainIntentService.PROMOTE_SUBKEY_IDS, subKeyIds); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); // Create a new Messenger for the communication back @@ -219,7 +226,7 @@ public class ViewKeyYubiKeyFragment extends Fragment } - public Integer naiveIndexOf(byte[][] haystack, byte[] needle) { + static private Integer naiveIndexOf(byte[][] haystack, byte[] needle) { for (int i = 0; i < haystack.length; i++) { if (Arrays.equals(needle, haystack[i])) { return i; diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 45b1dc26b..504c9497c 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -996,8 +996,11 @@ "Promoting public key to secret key" + "Promoting all subkeysp" "Key not found!" "Fetching key to modify (%s)" + "Promoting subkey: %s" + "Subkey not on Yubikey: %s" "Key successfully promoted" -- cgit v1.2.3 From 9a6f581400d04339f12dc008f4c38bef1134b6dc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 00:54:09 +0200 Subject: load yubikey fragment after mMasterKeyId is available --- .../keychain/ui/ViewKeyActivity.java | 50 ++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'OpenKeychain/src/main') 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 023483193..4237deff0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -131,6 +131,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements private boolean mIsRevoked = false; private boolean mIsExpired = false; + private boolean mShowYubikeyAfterCreation = false; + private MenuItem mRefreshItem; private boolean mIsRefreshing; private Animation mRotate, mRotateSpin; @@ -286,13 +288,9 @@ public class ViewKeyActivity extends BaseNfcActivity implements .replace(R.id.view_key_fragment, frag) .commit(); - if (getIntent().hasExtra(EXTRA_NFC_AID)) { - Intent intent = getIntent(); - byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS); - String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID); - byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID); - showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid); - } + // need to postpone loading of the yubikey fragment until after mMasterKeyId + // is available, but we mark here that this should be done + mShowYubikeyAfterCreation = true; } @@ -586,18 +584,26 @@ public class ViewKeyActivity extends BaseNfcActivity implements } - public void showYubiKeyFragment(byte[] nfcFingerprints, String nfcUserId, byte[] nfcAid) { - ViewKeyYubiKeyFragment frag = ViewKeyYubiKeyFragment.newInstance( - mMasterKeyId, nfcFingerprints, nfcUserId, nfcAid); + public void showYubiKeyFragment( + final byte[] nfcFingerprints, final String nfcUserId, final byte[] nfcAid) { - FragmentManager manager = getSupportFragmentManager(); + new Handler().post(new Runnable() { + @Override + public void run() { + ViewKeyYubiKeyFragment frag = ViewKeyYubiKeyFragment.newInstance( + mMasterKeyId, nfcFingerprints, nfcUserId, nfcAid); + + FragmentManager manager = getSupportFragmentManager(); + + manager.popBackStack("yubikey", FragmentManager.POP_BACK_STACK_INCLUSIVE); + manager.beginTransaction() + .addToBackStack("yubikey") + .replace(R.id.view_key_fragment, frag) + // if this is called while the activity wasn't resumed, just forget it happened + .commitAllowingStateLoss(); + } + }); - manager.popBackStack("yubikey", FragmentManager.POP_BACK_STACK_INCLUSIVE); - manager.beginTransaction() - .addToBackStack("yubikey") - .replace(R.id.view_key_fragment, frag) - // if this is called while the activity wasn't resumed, just forget it happened - .commitAllowingStateLoss(); } private void encrypt(Uri dataUri, boolean text) { @@ -813,6 +819,16 @@ public class ViewKeyActivity extends BaseNfcActivity implements mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT)); + // if it wasn't shown yet, display yubikey fragment + if (mShowYubikeyAfterCreation && getIntent().hasExtra(EXTRA_NFC_AID)) { + mShowYubikeyAfterCreation = false; + Intent intent = getIntent(); + byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS); + String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID); + byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID); + showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid); + } + mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0; mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0; -- cgit v1.2.3 From 765990ed13c9452d1488defd30d6537b762e5628 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 00:59:50 +0200 Subject: fingerprints are 20 bytes, not 40. duh. --- .../java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java index ecd351965..78a6ac55a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java @@ -83,7 +83,7 @@ public class ViewKeyYubiKeyFragment extends Fragment Bundle args = getArguments(); ByteBuffer buf = ByteBuffer.wrap(args.getByteArray(ARG_FINGERPRINT)); - mFingerprints = new byte[buf.remaining()/40][]; + mFingerprints = new byte[buf.remaining()/20][]; for (int i = 0; i < mFingerprints.length; i++) { mFingerprints[i] = new byte[20]; buf.get(mFingerprints[i]); -- cgit v1.2.3 From 3a27a28c0a9cee91b98b42b5e97d5312b8d25326 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 01:13:41 +0200 Subject: re-parcel log in LogDisplayFragment --- .../keychain/ui/LogDisplayFragment.java | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 138f2f4e7..3c8fbf8c9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -49,7 +49,6 @@ import org.sufficientlysecure.keychain.util.Log; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; -import java.util.Iterator; public class LogDisplayFragment extends ListFragment implements OnItemClickListener { @@ -58,6 +57,7 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe OperationResult mResult; public static final String EXTRA_RESULT = "log"; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -75,7 +75,12 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe return; } - mResult = intent.getParcelableExtra(EXTRA_RESULT); + if (savedInstanceState != null) { + mResult = savedInstanceState.getParcelable(EXTRA_RESULT); + } else { + mResult = intent.getParcelableExtra(EXTRA_RESULT); + } + if (mResult == null) { getActivity().finish(); return; @@ -91,6 +96,14 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + // need to parcel this again, logs are only single-instance parcelable + outState.putParcelable(EXTRA_RESULT, mResult); + } + @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { inflater.inflate(R.menu.log_display, menu); @@ -110,7 +123,6 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe } private void exportLog() { - showExportLogDialog(new File(Constants.Path.APP_DIR, "export.log")); } @@ -142,7 +154,9 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe } } - if (!error) currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_SUCCESS, 1); + if (!error) { + currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_SUCCESS, 1); + } int opResultCode = error ? OperationResult.RESULT_ERROR : OperationResult.RESULT_OK; OperationResult opResult = new LogExportResult(opResultCode, currLog); @@ -158,8 +172,8 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe */ private String getPrintableOperationLog(OperationResult.OperationLog opLog, String basePadding) { String log = ""; - for (Iterator logIterator = opLog.iterator(); logIterator.hasNext(); ) { - log += getPrintableLogEntry(logIterator.next(), basePadding) + "\n"; + for (LogEntryParcel anOpLog : opLog) { + log += getPrintableLogEntry(anOpLog, basePadding) + "\n"; } log = log.substring(0, log.length() - 1);//gets rid of extra new line return log; -- cgit v1.2.3 From a79d7bd1c280fda732a9550e88554fd9bb84bb1f Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 01:41:51 +0200 Subject: simplify MainActivity and fix backstack issues --- .../keychain/ui/MainActivity.java | 93 ++++++++-------------- 1 file changed, 33 insertions(+), 60 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java index f571ba1e6..78df612a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -44,12 +44,7 @@ import org.sufficientlysecure.keychain.util.Preferences; public class MainActivity extends AppCompatActivity implements FabContainer { - public Drawer.Result result; - - private KeyListFragment mKeyListFragment ; - private AppsListFragment mAppsListFragment; - private EncryptDecryptOverviewFragment mEncryptDecryptOverviewFragment; - private Fragment mLastUsedFragment; + public Drawer.Result mDrawerResult; private Toolbar mToolbar; @Override @@ -57,25 +52,21 @@ public class MainActivity extends AppCompatActivity implements FabContainer { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); - //initialize FragmentLayout with KeyListFragment at first - Fragment mainFragment = new KeyListFragment(); - FragmentManager fm = getSupportFragmentManager(); - FragmentTransaction transaction = fm.beginTransaction(); - transaction.replace(R.id.main_fragment_container, mainFragment); - transaction.commit(); - mToolbar = (Toolbar) findViewById(R.id.toolbar); mToolbar.setTitle(R.string.app_name); setSupportActionBar(mToolbar); - result = new Drawer() + mDrawerResult = new Drawer() .withActivity(this) .withHeader(R.layout.main_drawer_header) .withToolbar(mToolbar) .addDrawerItems( - new PrimaryDrawerItem().withName(R.string.nav_keys).withIcon(CommunityMaterial.Icon.cmd_key).withIdentifier(1).withCheckable(false), - new PrimaryDrawerItem().withName(R.string.nav_encrypt_decrypt).withIcon(FontAwesome.Icon.faw_lock).withIdentifier(2).withCheckable(false), - new PrimaryDrawerItem().withName(R.string.title_api_registered_apps).withIcon(CommunityMaterial.Icon.cmd_apps).withIdentifier(3).withCheckable(false) + new PrimaryDrawerItem().withName(R.string.nav_keys).withIcon(CommunityMaterial.Icon.cmd_key) + .withIdentifier(1).withCheckable(false), + new PrimaryDrawerItem().withName(R.string.nav_encrypt_decrypt).withIcon(FontAwesome.Icon.faw_lock) + .withIdentifier(2).withCheckable(false), + new PrimaryDrawerItem().withName(R.string.title_api_registered_apps).withIcon(CommunityMaterial.Icon.cmd_apps) + .withIdentifier(3).withCheckable(false) ) .addStickyDrawerItems( // display and stick on bottom of drawer @@ -130,76 +121,58 @@ public class MainActivity extends AppCompatActivity implements FabContainer { OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); result.createNotify(this).show(); } - } - - private void clearFragments() { - mKeyListFragment = null; - mAppsListFragment = null; - mEncryptDecryptOverviewFragment = null; - getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - } + if (savedInstanceState == null) { + // initialize FragmentLayout with KeyListFragment at first + onKeysSelected(); + } - private void setFragment(Fragment fragment) { - setFragment(fragment, true); } private void setFragment(Fragment fragment, boolean addToBackStack) { - this.mLastUsedFragment = fragment; - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + + FragmentManager fragmentManager = getSupportFragmentManager(); + fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); + + FragmentTransaction ft = fragmentManager.beginTransaction(); ft.replace(R.id.main_fragment_container, fragment); if (addToBackStack) { ft.addToBackStack(null); } ft.commit(); + } - private boolean onKeysSelected() { + private void onKeysSelected() { mToolbar.setTitle(R.string.app_name); - clearFragments(); - - if (mKeyListFragment == null) { - mKeyListFragment = new KeyListFragment(); - } - - setFragment(mKeyListFragment, false); - return true; + Fragment frag = new KeyListFragment(); + setFragment(frag, false); } - private boolean onEnDecryptSelected() { + private void onEnDecryptSelected() { mToolbar.setTitle(R.string.nav_encrypt_decrypt); - clearFragments(); - if (mEncryptDecryptOverviewFragment == null) { - mEncryptDecryptOverviewFragment = new EncryptDecryptOverviewFragment(); - } - - setFragment(mEncryptDecryptOverviewFragment); - return true; + Fragment frag = new EncryptDecryptOverviewFragment(); + setFragment(frag, true); } - private boolean onAppsSelected() { + private void onAppsSelected() { mToolbar.setTitle(R.string.nav_apps); - clearFragments(); - if (mAppsListFragment == null) { - mAppsListFragment = new AppsListFragment(); - } - - setFragment(mAppsListFragment); - return true; + Fragment frag = new AppsListFragment(); + setFragment(frag, true); } @Override protected void onSaveInstanceState(Bundle outState) { - //add the values which need to be saved from the drawer to the bundle - outState = result.saveInstanceState(outState); + // add the values which need to be saved from the drawer to the bundle + outState = mDrawerResult.saveInstanceState(outState); super.onSaveInstanceState(outState); } @Override - public void onBackPressed(){ - //handle the back press :D close the drawer first and if the drawer is closed close the activity - if (result != null && result.isDrawerOpen()) { - result.closeDrawer(); + public void onBackPressed() { + // close the drawer first and if the drawer is closed do regular backstack handling + if (mDrawerResult != null && mDrawerResult.isDrawerOpen()) { + mDrawerResult.closeDrawer(); } else { super.onBackPressed(); } -- cgit v1.2.3 From fb96b6dfa9bcfd704e1237de5721583f50631b33 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 01:57:26 +0200 Subject: open ViewKeyActivity by subkey in NfcBaseActivity --- .../org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java index 1d09b281f..0dad65e77 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java @@ -222,11 +222,12 @@ public abstract class BaseNfcActivity extends BaseActivity { final String nfcUserId = nfcGetUserId(); final byte[] nfcAid = nfcGetAid(); - final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints); + final long subKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints); try { - CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId); - ring.getMasterKeyId(); + CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId)); + long masterKeyId = ring.getMasterKeyId(); Intent intent = new Intent( BaseNfcActivity.this, ViewKeyActivity.class); -- cgit v1.2.3 From b62ad4d79c1e90ca63dafcd0edece3bcb826b087 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 May 2015 10:36:14 +0200 Subject: check fingerprint length after scanning qr code Fixes #1281 --- .../operations/results/OperationResult.java | 3 +- .../keychain/ui/ImportKeysProxyActivity.java | 36 ++++++++++++++-------- OpenKeychain/src/main/res/values/strings.xml | 3 +- 3 files changed, 28 insertions(+), 14 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index d39ab3695..ad7feaea6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -711,7 +711,8 @@ public abstract class OperationResult implements Parcelable { MSG_ACC_SAVED (LogLevel.INFO, R.string.api_settings_save_msg), - MSG_WRONG_QR_CODE (LogLevel.INFO, R.string.import_qr_code_wrong), + MSG_WRONG_QR_CODE (LogLevel.ERROR, R.string.import_qr_code_wrong), + MSG_WRONG_QR_CODE_FP(LogLevel.ERROR, R.string.import_qr_code_fp), MSG_NO_VALID_ENC (LogLevel.ERROR, R.string.error_invalid_data), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java index dc8752d1a..77fa9cc0b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java @@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.SingletonResult; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; @@ -141,24 +142,35 @@ public class ImportKeysProxyActivity extends FragmentActivity { Log.d(Constants.TAG, "scanned: " + uri); // example: openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282 - if (uri != null && uri.getScheme() != null && uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) { - String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH); + if (uri == null || uri.getScheme() == null || + !uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) { + SingletonResult result = new SingletonResult( + SingletonResult.RESULT_ERROR, LogType.MSG_WRONG_QR_CODE); + Intent intent = new Intent(); + intent.putExtra(SingletonResult.EXTRA_RESULT, result); + returnResult(intent); + return; + } - if (ACTION_SCAN_WITH_RESULT.equals(action)) { - Intent result = new Intent(); - result.putExtra(EXTRA_FINGERPRINT, fingerprint); - setResult(RESULT_OK, result); - finish(); - } else { - importKeys(fingerprint); - } - } else { + String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH); + if (fingerprint.matches("[a-fA-F0-9]{40}")) { SingletonResult result = new SingletonResult( - SingletonResult.RESULT_ERROR, OperationResult.LogType.MSG_WRONG_QR_CODE); + SingletonResult.RESULT_ERROR, LogType.MSG_WRONG_QR_CODE_FP); Intent intent = new Intent(); intent.putExtra(SingletonResult.EXTRA_RESULT, result); returnResult(intent); + return; + } + + if (ACTION_SCAN_WITH_RESULT.equals(action)) { + Intent result = new Intent(); + result.putExtra(EXTRA_FINGERPRINT, fingerprint); + setResult(RESULT_OK, result); + finish(); + } else { + importKeys(fingerprint); } + } public void returnResult(Intent data) { diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 504c9497c..d09c60b0f 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -408,7 +408,8 @@ "QR Code/NFC" "Import selected keys" "QR Code malformed! Please try again!" - "Fingerprint is too short (< 16 characters)" + "Fingerprint is malformed or too short!" + "Fingerprint is too short!" "Scan QR Code" "Place your camera over the QR Code!" -- cgit v1.2.3 From 79b7cec94acfbba683e1c78d1576866c5fbd5d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 May 2015 18:27:04 +0200 Subject: Use Mode.ALPHANUMERIC for QR codes to save space --- .../org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java | 9 +++++---- .../org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 7 +++++-- .../keychain/ui/ViewKeyAdvShareFragment.java | 7 +++++-- .../org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java | 10 +++++++++- 4 files changed, 24 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java index d4858ee5d..e54852f1b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java @@ -85,11 +85,12 @@ public class QrCodeViewActivity extends BaseActivity { ActivityCompat.finishAfterTransition(QrCodeViewActivity.this); } - String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob); - String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; - + Uri uri = new Uri.Builder() + .scheme(Constants.FINGERPRINT_SCHEME) + .opaquePart(KeyFormattingUtils.convertFingerprintToHex(blob)) + .build(); // create a minimal size qr code, we can keep this in ram no problem - final Bitmap qrCode = QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0); + final Bitmap qrCode = QrCodeUtils.getQRCodeBitmap(uri, 0); mQrCode.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { 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 4237deff0..9968855f7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -731,9 +731,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements AsyncTask loadTask = new AsyncTask() { protected Bitmap doInBackground(Void... unused) { - String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + Uri uri = new Uri.Builder() + .scheme(Constants.FINGERPRINT_SCHEME) + .opaquePart(fingerprint) + .build(); // render with minimal size - return QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0); + return QrCodeUtils.getQRCodeBitmap(uri, 0); } protected void onPostExecute(Bitmap qrCode) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java index fde0f62fd..479ddae0b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -386,9 +386,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements AsyncTask loadTask = new AsyncTask() { protected Bitmap doInBackground(Void... unused) { - String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + Uri uri = new Uri.Builder() + .scheme(Constants.FINGERPRINT_SCHEME) + .opaquePart(fingerprint) + .build(); // render with minimal size - return QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0); + return QrCodeUtils.getQRCodeBitmap(uri, 0); } protected void onPostExecute(Bitmap qrCode) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java index 5f71abdab..a6394a3fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.util; import android.graphics.Bitmap; import android.graphics.Color; +import android.net.Uri; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; @@ -33,17 +34,24 @@ import org.sufficientlysecure.keychain.KeychainApplication; import org.sufficientlysecure.keychain.util.Log; import java.util.Hashtable; +import java.util.Locale; /** * Copied from Bitcoin Wallet */ public class QrCodeUtils { + public static Bitmap getQRCodeBitmap(final Uri uri, final int size) { + // for URIs we want alphanumeric encoding to save space, thus make everything upper case! + // zxing will then select Mode.ALPHANUMERIC internally + return getQRCodeBitmap(uri.toString().toUpperCase(Locale.ENGLISH), size); + } + /** * Generate Bitmap with QR Code based on input. * @return QR Code as Bitmap */ - public static Bitmap getQRCodeBitmap(final String input, final int size) { + private static Bitmap getQRCodeBitmap(final String input, final int size) { try { -- cgit v1.2.3 From 0df51b614015279b83b2c4059039ed3ac076ba62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 May 2015 19:07:58 +0200 Subject: Fix fingerprint length check in QR Code import --- .../org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java index 77fa9cc0b..7ed8dd0b5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java @@ -153,7 +153,7 @@ public class ImportKeysProxyActivity extends FragmentActivity { } String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH); - if (fingerprint.matches("[a-fA-F0-9]{40}")) { + if (!fingerprint.matches("[a-fA-F0-9]{40}")) { SingletonResult result = new SingletonResult( SingletonResult.RESULT_ERROR, LogType.MSG_WRONG_QR_CODE_FP); Intent intent = new Intent(); -- cgit v1.2.3 From f30900d085f38034708f62f94e46a38f222d4cb7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 May 2015 12:47:02 +0200 Subject: add user id flags to UserAttribute self signatures --- .../keychain/pgp/PgpKeyOperation.java | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 89db378a9..2f771d8f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -553,7 +553,8 @@ public class PgpKeyOperation { PGPSignature cert = generateUserAttributeSignature( getSignatureGenerator(masterSecretKey, cryptoInput), cryptoInput.getSignatureTime(), - masterPrivateKey, masterPublicKey, vector); + masterPrivateKey, masterPublicKey, vector, + masterKeyFlags, masterKeyExpiry); modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert); } catch (NfcInteractionNeeded e) { nfcSignOps.addHash(e.hashToSign, e.hashAlgo); @@ -1319,11 +1320,9 @@ public class PgpKeyOperation { } - private PGPSignature generateUserIdSignature( - PGPSignatureGenerator sGen, Date creationTime, - PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary, - int flags, long expiry) - throws IOException, PGPException, SignatureException { + private static PGPSignatureSubpacketGenerator generateHashedSelfSigSubpackets( + Date creationTime, PGPPublicKey pKey, boolean primary, int flags, long expiry + ) { PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); { @@ -1357,6 +1356,17 @@ public class PgpKeyOperation { } } + return hashedPacketsGen; + } + + private static PGPSignature generateUserIdSignature( + PGPSignatureGenerator sGen, Date creationTime, + PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary, + int flags, long expiry) + throws IOException, PGPException, SignatureException { + + PGPSignatureSubpacketGenerator hashedPacketsGen = + generateHashedSelfSigSubpackets(creationTime, pKey, primary, flags, expiry); sGen.setHashedSubpackets(hashedPacketsGen.generate()); sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey); return sGen.generateCertification(userId, pKey); @@ -1365,15 +1375,12 @@ public class PgpKeyOperation { private static PGPSignature generateUserAttributeSignature( PGPSignatureGenerator sGen, Date creationTime, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, - PGPUserAttributeSubpacketVector vector) + PGPUserAttributeSubpacketVector vector, + int flags, long expiry) throws IOException, PGPException, SignatureException { - PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - { - /* critical subpackets: we consider those important for a modern pgp implementation */ - hashedPacketsGen.setSignatureCreationTime(true, creationTime); - } - + PGPSignatureSubpacketGenerator hashedPacketsGen = + generateHashedSelfSigSubpackets(creationTime, pKey, false, flags, expiry); sGen.setHashedSubpackets(hashedPacketsGen.generate()); sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey); return sGen.generateCertification(vector, pKey); -- cgit v1.2.3 From 6b6ca4c18ef96517829fcea954b3d46ff776a881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 May 2015 10:31:46 +0200 Subject: Fix language based on feedback from transifex --- .../sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java | 2 +- .../java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java | 2 +- OpenKeychain/src/main/res/values/strings.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java index f8d79d33b..e2c36c60d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java @@ -164,7 +164,7 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe if (!mNfcUserId.isEmpty()) { vUserId.setText(getString(R.string.yubikey_key_holder, mNfcUserId)); } else { - vUserId.setText(getString(R.string.yubikey_key_holder_unset)); + vUserId.setText(getString(R.string.yubikey_key_holder_not_set)); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java index 78a6ac55a..b02bb0b83 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java @@ -110,7 +110,7 @@ public class ViewKeyYubiKeyFragment extends Fragment if (!mUserId.isEmpty()) { vUserId.setText(getString(R.string.yubikey_key_holder, mUserId)); } else { - vUserId.setText(getString(R.string.yubikey_key_holder_unset)); + vUserId.setText(getString(R.string.yubikey_key_holder_not_set)); } vButton = (Button) view.findViewById(R.id.button_bind); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index d09c60b0f..98d91d3cf 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1284,7 +1284,7 @@ "Bind Key" "Serial No: %s" "Key holder: " - "Key holder: <unset>" + "Key holder: <not set>" "YubiKey matches and is bound to key" "YubiKey matches, can be bound to key" "YubiKey matches, partly bound to key" -- cgit v1.2.3 From 95875d727ef76ad7558217af8a924f05e6e023d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 May 2015 10:34:39 +0200 Subject: Version 3.2.2 --- OpenKeychain/src/main/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 332930dfb..804239e0c 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -3,8 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" package="org.sufficientlysecure.keychain" android:installLocation="auto" - android:versionCode="32100" - android:versionName="3.2.1"> + android:versionCode="32200" + android:versionName="3.2.2"> - "No search parameter found. You may still attempt manually searching the keyserver." + "No search query defined. You can still manually search on this keyserver." "Details" @@ -657,7 +657,7 @@ "<none>" - "Add Keyserver" + "Add keyserver" "Keyserver verified!" "Keyserver added without verification." "Invalid URL!" @@ -801,7 +801,7 @@ "Marked secret subkey %s as available, with empty password" "Marked secret subkey %s as available, with PIN" "Marked secret subkey %s as stripped" - "Marked secret subkey %s as 'divert to smartcard/NFC'" + "Marked secret subkey %s as 'divert-to-card'" "Keyring contains no new data, nothing to do" "Successfully imported secret keyring" @@ -908,8 +908,8 @@ "Modifying keyring %s" - "Will divert to card/nfc for crypto operations" - "The serial number of a divert-to-card key must be 16 bytes! This is a programming error, please file a bug report!" + "Will divert to smart card for crypto operations" + "The serial number of a 'divert-to-card' key must be 16 bytes! This is a programming error, please file a bug report!" "Encoding exception!" "Actual key fingerprint does not match the expected one!" "No key ID. This is an internal error, please file a bug report!" @@ -925,6 +925,12 @@ "Internal OpenPGP error!" "Signature exception!" "Tried to operate on missing subkey %s!" +<<<<<<< HEAD +======= + "Cannot move key to smart card in same operation that creates an on-card signature." + "Smart card supports only one slot per key type." + "Inappropriate key flags for smart card key." +>>>>>>> 0f52097... Improve strings "Modifying master certifications" "Adding empty notation packet" "Adding PIN notation packet" @@ -936,13 +942,18 @@ "Generating new certificate for new primary user ID" "Changing to restricted operation mode" "Modifying subkey %s" - "Diverting to card/nfc for crypto operations" + "Diverting to smart card for crypto operations" "Password required for operations" "Adding new subkey of type %s" "New subkey ID: %s" "Expiry date cannot be in the past!" "Revoking subkey %s" "Stripping subkey %s" +<<<<<<< HEAD +======= + "Moving subkey %s to smart card" + "Moved %1$s to smart card %2$s" +>>>>>>> 0f52097... Improve strings "Keyring successfully modified" "Adding user ID %s" "Changing primary user ID to %s" @@ -997,11 +1008,11 @@ "Promoting public key to secret key" - "Promoting all subkeysp" + "Promoting all subkeys" "Key not found!" "Fetching key to modify (%s)" "Promoting subkey: %s" - "Subkey not on Yubikey: %s" + "Subkey not on YubiKey: %s" "Key successfully promoted" @@ -1117,7 +1128,7 @@ "Error unlocking master key!" "Certifying keyrings" "Fetching certifying master key" - "Returning for NFC input" + "Returning to NFC screen" "Saving certified key %s" "Saving keyrings" "Unlocking master key" @@ -1217,6 +1228,11 @@ "Import key from file" "Use YubiKey NEO" "Skip Setup" +<<<<<<< HEAD +======= + "Blank smart card / YubiKey detected" + "Would you like to generate a smart card compatible key?" +>>>>>>> 0f52097... Improve strings "Certifier" @@ -1234,7 +1250,7 @@ "Key not found!" "Error processing key!" "stripped" - "divert to smartcard/NFC" + "divert to smart card" "no password" "unavailable" "Your own keys can only be deleted individually!" diff --git a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml b/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml index 08855fa22..d14f0bc40 100644 --- a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml +++ b/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml @@ -1,20 +1,21 @@ - - - + android:title="@string/pref_keyserver" /> + + + \ No newline at end of file -- cgit v1.2.3 From 79e356e04f8053d87fd2b1db5c2f9ea5dcd8f989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 May 2015 11:00:52 +0200 Subject: Change convertFingerprintToHex to use RuntimeException --- .../keychain/ui/util/KeyFormattingUtils.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index 2dea885a7..47cbc88ca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -218,14 +218,11 @@ public class KeyFormattingUtils { public static String convertFingerprintToHex(byte[] fingerprint) { // NOTE: Even though v3 keys are not imported we need to support both fingerprints for // display/comparison before import - // Also better cut of unneeded parts, e.g., for fingerprints returned from YubiKeys - if (fingerprint.length < 20) { - // v3 key fingerprint with 128 bit (MD5) - return Hex.toHexString(fingerprint, 0, 16).toLowerCase(Locale.ENGLISH); - } else { - // v4 key fingerprint with 160 bit (SHA1) - return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH); + if (fingerprint.length != 16 && fingerprint.length != 20) { + throw new RuntimeException("No valid v3 or v4 fingerprint!"); } + + return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); } public static long getKeyIdFromFingerprint(byte[] fingerprint) { -- cgit v1.2.3 From 08afe42ea6b90d911709dcae6a9480eb0bf5ce5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 May 2015 13:32:22 +0200 Subject: AssertionError instead of RuntimeException --- .../org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index 47cbc88ca..10c1aca0c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -219,7 +219,7 @@ public class KeyFormattingUtils { // NOTE: Even though v3 keys are not imported we need to support both fingerprints for // display/comparison before import if (fingerprint.length != 16 && fingerprint.length != 20) { - throw new RuntimeException("No valid v3 or v4 fingerprint!"); + throw new AssertionError("No valid v3 or v4 fingerprint!"); } return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); -- cgit v1.2.3 From e378c478145df32a981f7b3adbacad5950b3c6cc Mon Sep 17 00:00:00 2001 From: Yoshi64Bit Date: Sat, 23 May 2015 07:49:45 +0200 Subject: highlight currently selected item in navigation drawer --- .../keychain/ui/MainActivity.java | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java index e63e28667..008433f78 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -44,6 +44,12 @@ import org.sufficientlysecure.keychain.util.Preferences; public class MainActivity extends BaseNfcActivity implements FabContainer { + private static final int ID_KEYS = 1; + private static final int ID_ENCRYPT_DECRYPT = 2; + private static final int ID_APPS = 3; + private static final int ID_SETTINGS = 4; + private static final int ID_HELP = 5; + public Drawer.Result mDrawerResult; private Toolbar mToolbar; @@ -62,16 +68,16 @@ public class MainActivity extends BaseNfcActivity implements FabContainer { .withToolbar(mToolbar) .addDrawerItems( new PrimaryDrawerItem().withName(R.string.nav_keys).withIcon(CommunityMaterial.Icon.cmd_key) - .withIdentifier(1).withCheckable(false), + .withIdentifier(ID_KEYS).withCheckable(false), new PrimaryDrawerItem().withName(R.string.nav_encrypt_decrypt).withIcon(FontAwesome.Icon.faw_lock) - .withIdentifier(2).withCheckable(false), + .withIdentifier(ID_ENCRYPT_DECRYPT).withCheckable(false), new PrimaryDrawerItem().withName(R.string.title_api_registered_apps).withIcon(CommunityMaterial.Icon.cmd_apps) - .withIdentifier(3).withCheckable(false) + .withIdentifier(ID_APPS).withCheckable(false) ) .addStickyDrawerItems( // display and stick on bottom of drawer - new PrimaryDrawerItem().withName(R.string.menu_preferences).withIcon(GoogleMaterial.Icon.gmd_settings).withIdentifier(4).withCheckable(false), - new PrimaryDrawerItem().withName(R.string.menu_help).withIcon(CommunityMaterial.Icon.cmd_help_circle).withIdentifier(5).withCheckable(false) + new PrimaryDrawerItem().withName(R.string.menu_preferences).withIcon(GoogleMaterial.Icon.gmd_settings).withIdentifier(ID_SETTINGS).withCheckable(false), + new PrimaryDrawerItem().withName(R.string.menu_help).withIcon(CommunityMaterial.Icon.cmd_help_circle).withIdentifier(ID_HELP).withCheckable(false) ) .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { @Override @@ -79,19 +85,19 @@ public class MainActivity extends BaseNfcActivity implements FabContainer { if (drawerItem != null) { Intent intent = null; switch(drawerItem.getIdentifier()) { - case 1: + case ID_KEYS: onKeysSelected(); break; - case 2: + case ID_ENCRYPT_DECRYPT: onEnDecryptSelected(); break; - case 3: + case ID_APPS: onAppsSelected(); break; - case 4: + case ID_SETTINGS: intent = new Intent(MainActivity.this, SettingsActivity.class); break; - case 5: + case ID_HELP: intent = new Intent(MainActivity.this, HelpActivity.class); break; } @@ -145,18 +151,21 @@ public class MainActivity extends BaseNfcActivity implements FabContainer { private void onKeysSelected() { mToolbar.setTitle(R.string.app_name); + mDrawerResult.setSelectionByIdentifier(ID_KEYS, false); Fragment frag = new KeyListFragment(); setFragment(frag, false); } private void onEnDecryptSelected() { mToolbar.setTitle(R.string.nav_encrypt_decrypt); + mDrawerResult.setSelectionByIdentifier(ID_ENCRYPT_DECRYPT, false); Fragment frag = new EncryptDecryptOverviewFragment(); setFragment(frag, true); } private void onAppsSelected() { mToolbar.setTitle(R.string.nav_apps); + mDrawerResult.setSelectionByIdentifier(ID_APPS, false); Fragment frag = new AppsListFragment(); setFragment(frag, true); } -- cgit v1.2.3 From e03e1e5cfcc19b3898b3a6397f2d429c7779d343 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 May 2015 18:10:18 +0200 Subject: fix nullpointer in encrypttextactivity. fixes #1267 --- .../keychain/ui/EncryptTextActivity.java | 42 ++++++++++------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 52d098adc..82f057895 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -59,22 +59,7 @@ public class EncryptTextActivity extends BaseActivity implements } }, false); - // Handle intent actions - handleActions(getIntent(), savedInstanceState); - } - - @Override - protected void initLayout() { - setContentView(R.layout.encrypt_text_activity); - } - - - /** - * Handles all actions with this intent - * - * @param intent - */ - private void handleActions(Intent intent, Bundle savedInstanceState) { + Intent intent = getIntent(); String action = intent.getAction(); Bundle extras = intent.getExtras(); String type = intent.getType(); @@ -83,10 +68,6 @@ public class EncryptTextActivity extends BaseActivity implements extras = new Bundle(); } - /* - * Android's Action - */ - // When sending to OpenKeychain Encrypt via share menu if (Intent.ACTION_SEND.equals(action) && type != null) { Log.logDebugBundle(extras, "extras"); @@ -127,6 +108,11 @@ public class EncryptTextActivity extends BaseActivity implements } } + @Override + protected void initLayout() { + setContentView(R.layout.encrypt_text_activity); + } + @Override public void onModeChanged(boolean symmetric) { // switch fragments @@ -142,21 +128,29 @@ public class EncryptTextActivity extends BaseActivity implements @Override public void onSignatureKeyIdChanged(long signatureKeyId) { - mEncryptFragment.setSigningKeyId(signatureKeyId); + if (mEncryptFragment != null) { + mEncryptFragment.setSigningKeyId(signatureKeyId); + } } @Override public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds) { - mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds); + if (mEncryptFragment != null) { + mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds); + } } @Override public void onEncryptionUserIdsChanged(String[] encryptionUserIds) { - mEncryptFragment.setEncryptionUserIds(encryptionUserIds); + if (mEncryptFragment != null) { + mEncryptFragment.setEncryptionUserIds(encryptionUserIds); + } } @Override public void onPassphraseChanged(Passphrase passphrase) { - mEncryptFragment.setSymmetricPassphrase(passphrase); + if (mEncryptFragment != null) { + mEncryptFragment.setSymmetricPassphrase(passphrase); + } } } -- cgit v1.2.3 From 8f3e0a91106b26e0e32451d2f39724155fd2ecc6 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 May 2015 21:15:36 +0200 Subject: rewrite EncryptActivity data flow --- .../keychain/ui/CertifyKeyFragment.java | 16 +- .../keychain/ui/EncryptActivity.java | 77 +++++++++ .../keychain/ui/EncryptFilesActivity.java | 79 +--------- .../keychain/ui/EncryptFilesFragment.java | 173 +++++++++------------ .../keychain/ui/EncryptModeAsymmetricFragment.java | 111 +++++-------- .../keychain/ui/EncryptModeFragment.java | 19 +++ .../keychain/ui/EncryptModeSymmetricFragment.java | 86 +++++----- .../keychain/ui/EncryptTextActivity.java | 70 +-------- .../keychain/ui/EncryptTextFragment.java | 167 ++++++++------------ .../keychain/ui/widget/KeySpinner.java | 25 +-- 10 files changed, 346 insertions(+), 477 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeFragment.java (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 59623a610..df755edef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -77,8 +77,6 @@ public class CertifyKeyFragment extends CryptoOperationFragment private long[] mPubMasterKeyIds; - private long mSignMasterKeyId = Constants.key.none; - public static final String[] USER_IDS_PROJECTION = new String[]{ UserPackets._ID, UserPackets.MASTER_KEY_ID, @@ -149,19 +147,13 @@ public class CertifyKeyFragment extends CryptoOperationFragment vActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light), PorterDuff.Mode.SRC_IN); - mCertifyKeySpinner.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() { - @Override - public void onKeyChanged(long masterKeyId) { - mSignMasterKeyId = masterKeyId; - } - }); - View vCertifyButton = view.findViewById(R.id.certify_key_certify_button); vCertifyButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - if (mSignMasterKeyId == Constants.key.none) { + long selectedKeyId = mCertifyKeySpinner.getSelectedKeyId(); + if (selectedKeyId == Constants.key.none) { Notify.create(getActivity(), getString(R.string.select_key_to_certify), Notify.Style.ERROR).show(); } else { @@ -307,8 +299,10 @@ public class CertifyKeyFragment extends CryptoOperationFragment Bundle data = new Bundle(); { + long selectedKeyId = mCertifyKeySpinner.getSelectedKeyId(); + // fill values for this action - CertifyActionsParcel parcel = new CertifyActionsParcel(mSignMasterKeyId); + CertifyActionsParcel parcel = new CertifyActionsParcel(selectedKeyId); parcel.mCertifyActions.addAll(certifyActions); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java new file mode 100644 index 000000000..9fd3a4988 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.base.BaseActivity; + +public class EncryptActivity extends BaseActivity { + + // preselect ids, for internal use + public static final String EXTRA_SIGNATURE_KEY_ID = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_ID"; + public static final String EXTRA_ENCRYPTION_KEY_IDS = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_IDS"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + if (savedInstanceState == null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + // preselect keys given by intent + long signingKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); + long[] encryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); + + Fragment modeFragment = EncryptModeAsymmetricFragment.newInstance(signingKeyId, encryptionKeyIds); + transaction.replace(R.id.encrypt_mode_container, modeFragment); + transaction.commit(); + } + } + + public void toggleModeFragment() { + boolean symmetric = getModeFragment() instanceof EncryptModeAsymmetricFragment; + + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.encrypt_mode_container, + symmetric + ? EncryptModeSymmetricFragment.newInstance() + : EncryptModeAsymmetricFragment.newInstance(0, null) + ); + + // doesn't matter if the user doesn't look at the activity + transaction.commitAllowingStateLoss(); + } + + public EncryptModeFragment getModeFragment() { + return (EncryptModeFragment) + getSupportFragmentManager().findFragmentById(R.id.encrypt_mode_container); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index b3ec60890..45700f978 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -18,39 +18,25 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.view.View; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; -import org.sufficientlysecure.keychain.ui.base.BaseActivity; -import org.sufficientlysecure.keychain.util.Passphrase; import java.util.ArrayList; -public class EncryptFilesActivity extends BaseActivity implements - EncryptModeAsymmetricFragment.IAsymmetric, EncryptModeSymmetricFragment.ISymmetric, - EncryptFilesFragment.IMode { +public class EncryptFilesActivity extends EncryptActivity { - /* Intents */ + // Intents public static final String ACTION_ENCRYPT_DATA = OpenKeychainIntents.ENCRYPT_DATA; // enables ASCII Armor for file encryption when uri is given public static final String EXTRA_ASCII_ARMOR = OpenKeychainIntents.ENCRYPT_EXTRA_ASCII_ARMOR; - // preselect ids, for internal use - public static final String EXTRA_SIGNATURE_KEY_ID = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_ID"; - public static final String EXTRA_ENCRYPTION_KEY_IDS = Constants.EXTRA_PREFIX + "EXTRA_ENCRYPTION_IDS"; - - Fragment mModeFragment; - EncryptFilesFragment mEncryptFragment; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -62,19 +48,7 @@ public class EncryptFilesActivity extends BaseActivity implements } }, false); - // Handle intent actions - handleActions(getIntent(), savedInstanceState); - } - - @Override - protected void initLayout() { - setContentView(R.layout.encrypt_files_activity); - } - - /** - * Handles all actions with this intent - */ - private void handleActions(Intent intent, Bundle savedInstanceState) { + Intent intent = getIntent(); String action = intent.getAction(); Bundle extras = intent.getExtras(); String type = intent.getType(); @@ -88,10 +62,6 @@ public class EncryptFilesActivity extends BaseActivity implements uris.add(intent.getData()); } - /* - * Android's Action - */ - // When sending to OpenKeychain Encrypt via share menu if (Intent.ACTION_SEND.equals(action) && type != null) { // Files via content provider, override uri and action @@ -103,56 +73,21 @@ public class EncryptFilesActivity extends BaseActivity implements uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); } - long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); - long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); boolean useArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, false); if (savedInstanceState == null) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - mModeFragment = EncryptModeAsymmetricFragment.newInstance(mSigningKeyId, mEncryptionKeyIds); - transaction.replace(R.id.encrypt_mode_container, mModeFragment, "mode"); - - mEncryptFragment = EncryptFilesFragment.newInstance(uris, useArmor); - transaction.replace(R.id.encrypt_file_container, mEncryptFragment, "files"); - + EncryptFilesFragment encryptFragment = EncryptFilesFragment.newInstance(uris, useArmor); + transaction.replace(R.id.encrypt_file_container, encryptFragment); transaction.commit(); - - getSupportFragmentManager().executePendingTransactions(); } - } - @Override - public void onModeChanged(boolean symmetric) { - // switch fragments - getSupportFragmentManager().beginTransaction() - .replace(R.id.encrypt_mode_container, - symmetric - ? EncryptModeSymmetricFragment.newInstance() - : EncryptModeAsymmetricFragment.newInstance(0, null) - ) - .commitAllowingStateLoss(); - getSupportFragmentManager().executePendingTransactions(); } @Override - public void onSignatureKeyIdChanged(long signatureKeyId) { - mEncryptFragment.setSigningKeyId(signatureKeyId); - } - - @Override - public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds) { - mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds); - } - - @Override - public void onEncryptionUserIdsChanged(String[] encryptionUserIds) { - mEncryptFragment.setEncryptionUserIds(encryptionUserIds); - } - - @Override - public void onPassphraseChanged(Passphrase passphrase) { - mEncryptFragment.setPassphrase(passphrase); + protected void initLayout() { + setContentView(R.layout.encrypt_files_activity); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 458810541..fa35cc9ac 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -72,19 +72,12 @@ import java.util.Set; public class EncryptFilesFragment extends CryptoOperationFragment { - public interface IMode { - public void onModeChanged(boolean symmetric); - } - public static final String ARG_USE_ASCII_ARMOR = "use_ascii_armor"; public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; - private IMode mModeInterface; - - private boolean mSymmetricMode = false; private boolean mUseArmor = false; private boolean mUseCompression = true; private boolean mDeleteAfterEncrypt = false; @@ -92,11 +85,6 @@ public class EncryptFilesFragment extends CryptoOperationFragment { private boolean mEncryptFilenames = true; private boolean mHiddenRecipients = false; - private long mEncryptionKeyIds[] = null; - private String mEncryptionUserIds[] = null; - private long mSigningKeyId = Constants.key.none; - private Passphrase mPassphrase = new Passphrase(); - private ArrayList mOutputUris = new ArrayList<>(); private RecyclerView mSelectedFiles; @@ -118,29 +106,11 @@ public class EncryptFilesFragment extends CryptoOperationFragment { return frag; } - public void setEncryptionKeyIds(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; - } - - public void setEncryptionUserIds(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; - } - - public void setSigningKeyId(long signingKeyId) { - mSigningKeyId = signingKeyId; - } - - public void setPassphrase(Passphrase passphrase) { - mPassphrase = passphrase; - } - @Override public void onAttach(Activity activity) { super.onAttach(activity); - try { - mModeInterface = (IMode) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity + " must be IMode"); + if ( ! (activity instanceof EncryptActivity) ) { + throw new AssertionError(activity + " must inherit from EncryptionActivity"); } } @@ -293,8 +263,8 @@ public class EncryptFilesFragment extends CryptoOperationFragment { break; } case R.id.check_use_symmetric: { - mSymmetricMode = item.isChecked(); - mModeInterface.onModeChanged(mSymmetricMode); + EncryptActivity encryptActivity = (EncryptActivity) getActivity(); + encryptActivity.toggleModeFragment(); break; } case R.id.check_use_armor: { @@ -325,53 +295,6 @@ public class EncryptFilesFragment extends CryptoOperationFragment { return true; } - protected boolean inputIsValid() { - // file checks - - if (mFilesModels.isEmpty()) { - Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR) - .show(this); - return false; - } else if (mFilesModels.size() > 1 && !mShareAfterEncrypt) { - Log.e(Constants.TAG, "Aborting: mInputUris.size() > 1 && !mShareAfterEncrypt"); - // This should be impossible... - return false; - } else if (mFilesModels.size() != mOutputUris.size()) { - Log.e(Constants.TAG, "Aborting: mInputUris.size() != mOutputUris.size()"); - // This as well - return false; - } - - if (mSymmetricMode) { - // symmetric encryption checks - - if (mPassphrase == null) { - Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR) - .show(this); - return false; - } - if (mPassphrase.isEmpty()) { - Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) - .show(this); - return false; - } - - } else { - // asymmetric encryption checks - - boolean gotEncryptionKeys = (mEncryptionKeyIds != null - && mEncryptionKeyIds.length > 0); - - // Files must be encrypted, only text can be signed-only right now - if (!gotEncryptionKeys) { - Notify.create(getActivity(), R.string.select_encryption_key, Notify.Style.ERROR) - .show(this); - return false; - } - } - return true; - } - public void onEncryptSuccess(final SignEncryptResult result) { if (mDeleteAfterEncrypt) { DeleteFileDialogFragment deleteFileDialog = @@ -403,6 +326,21 @@ public class EncryptFilesFragment extends CryptoOperationFragment { } protected SignEncryptParcel createEncryptBundle() { + + if (mFilesModels.isEmpty()) { + Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR) + .show(this); + return null; + } else if (mFilesModels.size() > 1 && !mShareAfterEncrypt) { + Log.e(Constants.TAG, "Aborting: mInputUris.size() > 1 && !mShareAfterEncrypt"); + // This should be impossible... + return null; + } else if (mFilesModels.size() != mOutputUris.size()) { + Log.e(Constants.TAG, "Aborting: mInputUris.size() != mOutputUris.size()"); + // This as well + return null; + } + // fill values for this action SignEncryptParcel data = new SignEncryptParcel(); @@ -419,17 +357,39 @@ public class EncryptFilesFragment extends CryptoOperationFragment { data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); - if (mSymmetricMode) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - Passphrase passphrase = mPassphrase; + EncryptActivity encryptActivity = (EncryptActivity) getActivity(); + EncryptModeFragment modeFragment = encryptActivity.getModeFragment(); + + if (modeFragment.isAsymmetric()) { + long[] encryptionKeyIds = modeFragment.getAsymmetricEncryptionKeyIds(); + long signingKeyId = modeFragment.getAsymmetricSigningKeyId(); + + boolean gotEncryptionKeys = (encryptionKeyIds != null + && encryptionKeyIds.length > 0); + + if (!gotEncryptionKeys && signingKeyId == 0) { + Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR) + .show(this); + return null; + } + + data.setEncryptionMasterKeyIds(encryptionKeyIds); + data.setSignatureMasterKeyId(signingKeyId); + } else { + Passphrase passphrase = modeFragment.getSymmetricPassphrase(); + if (passphrase == null) { + Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR) + .show(this); + return null; + } if (passphrase.isEmpty()) { - passphrase = null; + Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) + .show(this); + return null; } data.setSymmetricPassphrase(passphrase); - } else { - data.setEncryptionMasterKeyIds(mEncryptionKeyIds); - data.setSignatureMasterKeyId(mSigningKeyId); } + return data; } @@ -461,16 +421,27 @@ public class EncryptFilesFragment extends CryptoOperationFragment { } sendIntent.setType(Constants.ENCRYPTED_FILES_MIME); - if (!mSymmetricMode && mEncryptionUserIds != null) { - Set users = new HashSet<>(); - for (String user : mEncryptionUserIds) { - KeyRing.UserId userId = KeyRing.splitUserId(user); - if (userId.email != null) { - users.add(userId.email); - } + EncryptActivity modeInterface = (EncryptActivity) getActivity(); + EncryptModeFragment modeFragment = modeInterface.getModeFragment(); + if (!modeFragment.isAsymmetric()) { + return sendIntent; + } + + String[] encryptionUserIds = modeFragment.getAsymmetricEncryptionUserIds(); + if (encryptionUserIds == null) { + return sendIntent; + } + + Set users = new HashSet<>(); + for (String user : encryptionUserIds) { + KeyRing.UserId userId = KeyRing.splitUserId(user); + if (userId.email != null) { + users.add(userId.email); } - sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); } + // pass trough email addresses as extra for email applications + sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + return sendIntent; } @@ -482,19 +453,17 @@ public class EncryptFilesFragment extends CryptoOperationFragment { @Override protected void cryptoOperation(CryptoInputParcel cryptoInput) { - if (!inputIsValid()) { + final SignEncryptParcel input = createEncryptBundle(); + // this is null if invalid, just return in that case + if (input == null) { // Notify was created by inputIsValid. - Log.d(Constants.TAG, "Input not valid!"); return; } - Log.d(Constants.TAG, "Input valid!"); // Send all information needed to service to edit key in other thread Intent intent = new Intent(getActivity(), KeychainIntentService.class); intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT); - final SignEncryptParcel input = createEncryptBundle(); - Bundle data = new Bundle(); data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, input); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); @@ -727,7 +696,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment { for (Uri inputUri : inputUris) { ViewModel newModel = new ViewModel(mActivity, inputUri); if (mDataset.contains(newModel)) { - Log.e(Constants.TAG, "Skipped duplicate " + inputUri.toString()); + Log.e(Constants.TAG, "Skipped duplicate " + inputUri); } else { mDataset.add(newModel); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java index 6f56f2dc4..758d5f51a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java @@ -17,18 +17,13 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Activity; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.tokenautocomplete.TokenCompleteTextView; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -39,38 +34,19 @@ import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter.KeyItem; import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; import org.sufficientlysecure.keychain.ui.widget.KeySpinner; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Passphrase; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class EncryptModeAsymmetricFragment extends Fragment { - - public interface IAsymmetric { - - public void onSignatureKeyIdChanged(long signatureKeyId); - - public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds); - - public void onEncryptionUserIdsChanged(String[] encryptionUserIds); - } +public class EncryptModeAsymmetricFragment extends EncryptModeFragment { ProviderHelper mProviderHelper; - // view - private KeySpinner mSign; + private KeySpinner mSignKeySpinner; private EncryptKeyCompletionView mEncryptKeyView; - // model - private IAsymmetric mEncryptInterface; - -// @Override -// public void updateUi() { -// if (mSign != null) { -// mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey()); -// } -// } - public static final String ARG_SINGATURE_KEY_ID = "signature_key_id"; public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids"; @@ -89,16 +65,6 @@ public class EncryptModeAsymmetricFragment extends Fragment { return frag; } - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - mEncryptInterface = (IAsymmetric) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity + " must implement IAsymmetric"); - } - } - /** * Inflate the layout for this fragment */ @@ -106,13 +72,7 @@ public class EncryptModeAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSign = (KeySpinner) view.findViewById(R.id.sign); - mSign.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() { - @Override - public void onKeyChanged(long masterKeyId) { - mEncryptInterface.onSignatureKeyIdChanged(masterKeyId); - } - }); + mSignKeySpinner = (KeySpinner) view.findViewById(R.id.sign); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); mEncryptKeyView.setThreshold(1); // Start working from first character @@ -128,22 +88,6 @@ public class EncryptModeAsymmetricFragment extends Fragment { long signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID); long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS); preselectKeys(signatureKeyId, encryptionKeyIds); - - mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { - @Override - public void onTokenAdded(Object token) { - if (token instanceof KeyItem) { - updateEncryptionKeys(); - } - } - - @Override - public void onTokenRemoved(Object token) { - if (token instanceof KeyItem) { - updateEncryptionKeys(); - } - } - }); } /** @@ -155,8 +99,7 @@ public class EncryptModeAsymmetricFragment extends Fragment { CachedPublicKeyRing keyring = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(signatureKeyId)); if (keyring.hasAnySecret()) { - mEncryptInterface.onSignatureKeyIdChanged(keyring.getMasterKeyId()); - mSign.setSelectedKeyId(signatureKeyId); + mSignKeySpinner.setSelectedKeyId(signatureKeyId); } } catch (PgpKeyNotFoundException e) { Log.e(Constants.TAG, "key not found!", e); @@ -175,27 +118,55 @@ public class EncryptModeAsymmetricFragment extends Fragment { } // This is to work-around a rendering bug in TokenCompleteTextView mEncryptKeyView.requestFocus(); - updateEncryptionKeys(); } } - private void updateEncryptionKeys() { - List objects = mEncryptKeyView.getObjects(); + @Override + public boolean isAsymmetric() { + return true; + } + + @Override + public long getAsymmetricSigningKeyId() { + return mSignKeySpinner.getSelectedItemId(); + } + + @Override + public long[] getAsymmetricEncryptionKeyIds() { List keyIds = new ArrayList<>(); - List userIds = new ArrayList<>(); - for (Object object : objects) { + for (Object object : mEncryptKeyView.getObjects()) { if (object instanceof KeyItem) { keyIds.add(((KeyItem) object).mKeyId); - userIds.add(((KeyItem) object).mUserIdFull); } } + long[] keyIdsArr = new long[keyIds.size()]; Iterator iterator = keyIds.iterator(); for (int i = 0; i < keyIds.size(); i++) { keyIdsArr[i] = iterator.next(); } - mEncryptInterface.onEncryptionKeyIdsChanged(keyIdsArr); - mEncryptInterface.onEncryptionUserIdsChanged(userIds.toArray(new String[userIds.size()])); + + return keyIdsArr; + } + + @Override + public String[] getAsymmetricEncryptionUserIds() { + + List userIds = new ArrayList<>(); + for (Object object : mEncryptKeyView.getObjects()) { + if (object instanceof KeyItem) { + userIds.add(((KeyItem) object).mUserIdFull); + } + } + + return userIds.toArray(new String[userIds.size()]); + } + + @Override + public Passphrase getSymmetricPassphrase() { + throw new UnsupportedOperationException("should never happen, this is a programming error!"); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeFragment.java new file mode 100644 index 000000000..0b9672654 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeFragment.java @@ -0,0 +1,19 @@ +package org.sufficientlysecure.keychain.ui; + + +import android.support.v4.app.Fragment; + +import org.sufficientlysecure.keychain.util.Passphrase; + + +public abstract class EncryptModeFragment extends Fragment { + + public abstract boolean isAsymmetric(); + + public abstract long getAsymmetricSigningKeyId(); + public abstract long[] getAsymmetricEncryptionKeyIds(); + public abstract String[] getAsymmetricEncryptionUserIds(); + + public abstract Passphrase getSymmetricPassphrase(); + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java index 48b1f4983..b92a73731 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java @@ -17,11 +17,7 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Activity; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.text.Editable; -import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,14 +26,7 @@ import android.widget.EditText; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Passphrase; -public class EncryptModeSymmetricFragment extends Fragment { - - public interface ISymmetric { - - public void onPassphraseChanged(Passphrase passphrase); - } - - private ISymmetric mEncryptInterface; +public class EncryptModeSymmetricFragment extends EncryptModeFragment { private EditText mPassphrase; private EditText mPassphraseAgain; @@ -54,53 +43,54 @@ public class EncryptModeSymmetricFragment extends Fragment { return frag; } - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - mEncryptInterface = (ISymmetric) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement ISymmetric"); - } - } - - /** - * Inflate the layout for this fragment - */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_symmetric_fragment, container, false); mPassphrase = (EditText) view.findViewById(R.id.passphrase); mPassphraseAgain = (EditText) view.findViewById(R.id.passphraseAgain); - TextWatcher textWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } + return view; + } + + @Override + public boolean isAsymmetric() { + return false; + } - @Override - public void afterTextChanged(Editable s) { - // update passphrase in EncryptActivity - Passphrase p1 = new Passphrase(mPassphrase.getText()); - Passphrase p2 = new Passphrase(mPassphraseAgain.getText()); - boolean passesEquals = (p1.equals(p2)); + @Override + public long getAsymmetricSigningKeyId() { + throw new UnsupportedOperationException("should never happen, this is a programming error!"); + } + + @Override + public long[] getAsymmetricEncryptionKeyIds() { + throw new UnsupportedOperationException("should never happen, this is a programming error!"); + } + + @Override + public String[] getAsymmetricEncryptionUserIds() { + throw new UnsupportedOperationException("should never happen, this is a programming error!"); + } + + @Override + public Passphrase getSymmetricPassphrase() { + Passphrase p1 = null, p2 = null; + try { + p1 = new Passphrase(mPassphrase.getText()); + p2 = new Passphrase(mPassphraseAgain.getText()); + if (!p1.equals(p2)) { + return null; + } + return new Passphrase(mPassphrase.getText()); + } finally { + if (p1 != null) { p1.removeFromMemory(); + } + if (p2 != null) { p2.removeFromMemory(); - if (passesEquals) { - mEncryptInterface.onPassphraseChanged(new Passphrase(mPassphrase.getText())); - } else { - mEncryptInterface.onPassphraseChanged(null); - } } - }; - mPassphrase.addTextChangedListener(textWatcher); - mPassphraseAgain.addTextChangedListener(textWatcher); - - return view; + } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 82f057895..cb26ea452 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -20,20 +20,14 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.view.View; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; -import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Passphrase; -public class EncryptTextActivity extends BaseActivity implements - EncryptModeAsymmetricFragment.IAsymmetric, EncryptModeSymmetricFragment.ISymmetric, - EncryptTextFragment.IMode { +public class EncryptTextActivity extends EncryptActivity { /* Intents */ public static final String ACTION_ENCRYPT_TEXT = OpenKeychainIntents.ENCRYPT_TEXT; @@ -41,13 +35,6 @@ public class EncryptTextActivity extends BaseActivity implements /* EXTRA keys for input */ public static final String EXTRA_TEXT = OpenKeychainIntents.ENCRYPT_EXTRA_TEXT; - // preselect ids, for internal use - public static final String EXTRA_SIGNATURE_KEY_ID = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_ID"; - public static final String EXTRA_ENCRYPTION_KEY_IDS = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_IDS"; - - Fragment mModeFragment; - EncryptTextFragment mEncryptFragment; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -89,23 +76,14 @@ public class EncryptTextActivity extends BaseActivity implements textData = ""; } - // preselect keys given by intent - long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); - long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); - if (savedInstanceState == null) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - mModeFragment = EncryptModeAsymmetricFragment.newInstance(mSigningKeyId, mEncryptionKeyIds); - transaction.replace(R.id.encrypt_mode_container, mModeFragment, "mode"); - - mEncryptFragment = EncryptTextFragment.newInstance(textData); - transaction.replace(R.id.encrypt_text_container, mEncryptFragment, "text"); - + EncryptTextFragment encryptFragment = EncryptTextFragment.newInstance(textData); + transaction.replace(R.id.encrypt_text_container, encryptFragment); transaction.commit(); - - getSupportFragmentManager().executePendingTransactions(); } + } @Override @@ -113,44 +91,4 @@ public class EncryptTextActivity extends BaseActivity implements setContentView(R.layout.encrypt_text_activity); } - @Override - public void onModeChanged(boolean symmetric) { - // switch fragments - getSupportFragmentManager().beginTransaction() - .replace(R.id.encrypt_mode_container, - symmetric - ? EncryptModeSymmetricFragment.newInstance() - : EncryptModeAsymmetricFragment.newInstance(0, null) - ) - .commitAllowingStateLoss(); - getSupportFragmentManager().executePendingTransactions(); - } - - @Override - public void onSignatureKeyIdChanged(long signatureKeyId) { - if (mEncryptFragment != null) { - mEncryptFragment.setSigningKeyId(signatureKeyId); - } - } - - @Override - public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds) { - if (mEncryptFragment != null) { - mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds); - } - } - - @Override - public void onEncryptionUserIdsChanged(String[] encryptionUserIds) { - if (mEncryptFragment != null) { - mEncryptFragment.setEncryptionUserIds(encryptionUserIds); - } - } - - @Override - public void onPassphraseChanged(Passphrase passphrase) { - if (mEncryptFragment != null) { - mEncryptFragment.setSymmetricPassphrase(passphrase); - } - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 3f9147cc4..89bc97e16 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -47,7 +47,6 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.util.Notify; -import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.ShareHelper; @@ -56,44 +55,14 @@ import java.util.Set; public class EncryptTextFragment extends CryptoOperationFragment { - public interface IMode { - public void onModeChanged(boolean symmetric); - } - public static final String ARG_TEXT = "text"; - private IMode mModeInterface; - - private boolean mSymmetricMode = false; private boolean mShareAfterEncrypt = false; private boolean mUseCompression = true; private boolean mHiddenRecipients = false; - private long mEncryptionKeyIds[] = null; - private String mEncryptionUserIds[] = null; - // TODO Constants.key.none? What's wrong with a null value? - private long mSigningKeyId = Constants.key.none; - private Passphrase mSymmetricPassphrase = new Passphrase(); private String mMessage = ""; - private TextView mText; - - public void setEncryptionKeyIds(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; - } - - public void setEncryptionUserIds(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; - } - - public void setSigningKeyId(long signingKeyId) { - mSigningKeyId = signingKeyId; - } - - public void setSymmetricPassphrase(Passphrase passphrase) { - mSymmetricPassphrase = passphrase; - } - /** * Creates new instance of this fragment */ @@ -110,10 +79,8 @@ public class EncryptTextFragment extends CryptoOperationFragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); - try { - mModeInterface = (IMode) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement IMode"); + if ( ! (activity instanceof EncryptActivity) ) { + throw new AssertionError(activity + " must inherit from EncryptionActivity"); } } @@ -124,8 +91,8 @@ public class EncryptTextFragment extends CryptoOperationFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_text_fragment, container, false); - mText = (TextView) view.findViewById(R.id.encrypt_text_text); - mText.addTextChangedListener(new TextWatcher() { + TextView textView = (TextView) view.findViewById(R.id.encrypt_text_text); + textView.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -144,7 +111,7 @@ public class EncryptTextFragment extends CryptoOperationFragment { // set initial text if (mMessage != null) { - mText.setText(mMessage); + textView.setText(mMessage); } return view; @@ -171,8 +138,8 @@ public class EncryptTextFragment extends CryptoOperationFragment { } switch (item.getItemId()) { case R.id.check_use_symmetric: { - mSymmetricMode = item.isChecked(); - mModeInterface.onModeChanged(mSymmetricMode); + EncryptActivity modeInterface = (EncryptActivity) getActivity(); + modeInterface.toggleModeFragment(); break; } case R.id.check_enable_compression: { @@ -185,11 +152,11 @@ public class EncryptTextFragment extends CryptoOperationFragment { // break; // } case R.id.encrypt_copy: { - startEncrypt(false); + cryptoOperation(false); break; } case R.id.encrypt_share: { - startEncrypt(true); + cryptoOperation(true); break; } default: { @@ -199,7 +166,6 @@ public class EncryptTextFragment extends CryptoOperationFragment { return true; } - protected void onEncryptSuccess(SignEncryptResult result) { if (mShareAfterEncrypt) { // Share encrypted message/file @@ -215,6 +181,13 @@ public class EncryptTextFragment extends CryptoOperationFragment { } protected SignEncryptParcel createEncryptBundle() { + + if (mMessage == null || mMessage.isEmpty()) { + Notify.create(getActivity(), R.string.error_empty_text, Notify.Style.ERROR) + .show(this); + return null; + } + // fill values for this action SignEncryptParcel data = new SignEncryptParcel(); @@ -227,22 +200,45 @@ public class EncryptTextFragment extends CryptoOperationFragment { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } data.setHiddenRecipients(mHiddenRecipients); - data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); - data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + data.setSymmetricEncryptionAlgorithm( + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + data.setSignatureHashAlgorithm( + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); // Always use armor for messages data.setEnableAsciiArmorOutput(true); - if (mSymmetricMode) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - Passphrase passphrase = mSymmetricPassphrase; + EncryptActivity modeInterface = (EncryptActivity) getActivity(); + EncryptModeFragment modeFragment = modeInterface.getModeFragment(); + + if (modeFragment.isAsymmetric()) { + long[] encryptionKeyIds = modeFragment.getAsymmetricEncryptionKeyIds(); + long signingKeyId = modeFragment.getAsymmetricSigningKeyId(); + + boolean gotEncryptionKeys = (encryptionKeyIds != null + && encryptionKeyIds.length > 0); + + if (!gotEncryptionKeys && signingKeyId == 0L) { + Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR) + .show(this); + return null; + } + + data.setEncryptionMasterKeyIds(encryptionKeyIds); + data.setSignatureMasterKeyId(signingKeyId); + } else { + Passphrase passphrase = modeFragment.getSymmetricPassphrase(); + if (passphrase == null) { + Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR) + .show(this); + return null; + } if (passphrase.isEmpty()) { - passphrase = null; + Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) + .show(this); + return null; } data.setSymmetricPassphrase(passphrase); - } else { - data.setEncryptionMasterKeyIds(mEncryptionKeyIds); - data.setSignatureMasterKeyId(mSigningKeyId); } return data; } @@ -273,65 +269,41 @@ public class EncryptTextFragment extends CryptoOperationFragment { sendIntent.setType(Constants.ENCRYPTED_TEXT_MIME); sendIntent.putExtra(Intent.EXTRA_TEXT, new String(resultBytes)); - if (!mSymmetricMode && mEncryptionUserIds != null) { - Set users = new HashSet<>(); - for (String user : mEncryptionUserIds) { - KeyRing.UserId userId = KeyRing.splitUserId(user); - if (userId.email != null) { - users.add(userId.email); - } - } - // pass trough email addresses as extra for email applications - sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + EncryptActivity modeInterface = (EncryptActivity) getActivity(); + EncryptModeFragment modeFragment = modeInterface.getModeFragment(); + if (!modeFragment.isAsymmetric()) { + return sendIntent; } - return sendIntent; - } - protected boolean inputIsValid() { - if (mMessage == null || mMessage.isEmpty()) { - Notify.create(getActivity(), R.string.error_empty_text, Notify.Style.ERROR) - .show(this); - return false; + String[] encryptionUserIds = modeFragment.getAsymmetricEncryptionUserIds(); + if (encryptionUserIds == null) { + return sendIntent; } - if (mSymmetricMode) { - // symmetric encryption checks - - if (mSymmetricPassphrase == null) { - Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR) - .show(this); - return false; - } - if (mSymmetricPassphrase.isEmpty()) { - Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) - .show(this); - return false; - } - - } else { - // asymmetric encryption checks - - boolean gotEncryptionKeys = (mEncryptionKeyIds != null - && mEncryptionKeyIds.length > 0); - - if (!gotEncryptionKeys && mSigningKeyId == 0) { - Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR) - .show(this); - return false; + Set users = new HashSet<>(); + for (String user : encryptionUserIds) { + KeyRing.UserId userId = KeyRing.splitUserId(user); + if (userId.email != null) { + users.add(userId.email); } } - return true; - } + // pass trough email addresses as extra for email applications + sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + return sendIntent; + } - public void startEncrypt(boolean share) { + public void cryptoOperation(boolean share) { mShareAfterEncrypt = share; cryptoOperation(); } @Override protected void cryptoOperation(CryptoInputParcel cryptoInput) { - if (!inputIsValid()) { + + final SignEncryptParcel input = createEncryptBundle(); + // this is null if invalid, just return in that case + if (input == null) { // Notify was created by inputIsValid. return; } @@ -340,7 +312,6 @@ public class EncryptTextFragment extends CryptoOperationFragment { Intent intent = new Intent(getActivity(), KeychainIntentService.class); intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT); - final SignEncryptParcel input = createEncryptBundle(); final Bundle data = new Bundle(); data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, input); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index aecc81604..579f37db2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -20,12 +20,14 @@ package org.sufficientlysecure.keychain.ui.widget; import android.content.Context; import android.database.Cursor; import android.graphics.Color; +import android.os.Bundle; +import android.os.Parcelable; +import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.AppCompatSpinner; -import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; import android.view.View; @@ -42,17 +44,18 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - /** * Use AppCompatSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon. * Related: http://stackoverflow.com/a/27713090 */ -public abstract class KeySpinner extends AppCompatSpinner implements LoaderManager.LoaderCallbacks { +public abstract class KeySpinner extends AppCompatSpinner implements + LoaderManager.LoaderCallbacks { + + public static final String ARG_SUPER_STATE = "super_state"; + public static final String ARG_SELECTED_KEY_ID = "select_key_id"; + public interface OnKeyChangedListener { - public void onKeyChanged(long masterKeyId); + void onKeyChanged(long masterKeyId); } protected long mSelectedKeyId = Constants.key.none; @@ -82,15 +85,17 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManag super.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { + mSelectedKeyId = id; if (mListener != null) { - mListener.onKeyChanged(id); + mListener.onKeyChanged(mSelectedKeyId); } } @Override public void onNothingSelected(AdapterView parent) { + mSelectedKeyId = Constants.key.none; if (mListener != null) { - mListener.onKeyChanged(Constants.key.none); + mListener.onKeyChanged(mSelectedKeyId); } } }); @@ -138,7 +143,7 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManag } public void setSelectedKeyId(long selectedKeyId) { - this.mSelectedKeyId = selectedKeyId; + mSelectedKeyId = selectedKeyId; } protected class SelectKeyAdapter extends BaseAdapter implements SpinnerAdapter { -- cgit v1.2.3 From 7c20c8df932e108c4156a316ddc68ff3610bba4e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 May 2015 22:07:34 +0200 Subject: preserve state in KeySpinner, and some lint fixes --- .../remote/ui/AccountSettingsFragment.java | 4 +- .../keychain/ui/CertifyKeyFragment.java | 3 +- .../keychain/ui/EncryptModeAsymmetricFragment.java | 15 ++++--- .../keychain/ui/widget/CertifyKeySpinner.java | 2 +- .../keychain/ui/widget/KeySpinner.java | 46 ++++++++++++++++------ 5 files changed, 48 insertions(+), 22 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index 81181d61d..18afd2f23 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -58,7 +58,7 @@ public class AccountSettingsFragment extends Fragment { this.mAccSettings = accountSettings; mAccNameView.setText(accountSettings.getAccountName()); - mSelectKeySpinner.setSelectedKeyId(accountSettings.getKeyId()); + mSelectKeySpinner.setPreSelectedKeyId(accountSettings.getKeyId()); } /** @@ -107,7 +107,7 @@ public class AccountSettingsFragment extends Fragment { if (resultCode == Activity.RESULT_OK) { if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { EditKeyResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); - mSelectKeySpinner.setSelectedKeyId(result.mMasterKeyId); + mSelectKeySpinner.setPreSelectedKeyId(result.mMasterKeyId); } else { Log.e(Constants.TAG, "missing result!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index df755edef..4506d5efa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -60,7 +60,6 @@ import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner; -import org.sufficientlysecure.keychain.ui.widget.KeySpinner; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; @@ -113,7 +112,7 @@ public class CertifyKeyFragment extends CryptoOperationFragment try { CachedPublicKeyRing key = (new ProviderHelper(getActivity())).getCachedPublicKeyRing(certifyKeyId); if (key.canCertify()) { - mCertifyKeySpinner.setSelectedKeyId(certifyKeyId); + mCertifyKeySpinner.setPreSelectedKeyId(certifyKeyId); } } catch (PgpKeyNotFoundException e) { Log.e(Constants.TAG, "certify certify check failed", e); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java index 758d5f51a..3b4db6c08 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java @@ -84,10 +84,15 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment { super.onActivityCreated(savedInstanceState); mProviderHelper = new ProviderHelper(getActivity()); - // preselect keys given - long signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID); - long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS); - preselectKeys(signatureKeyId, encryptionKeyIds); + // preselect keys given, from state or arguments + long signatureKeyId, encryptionKeyIds[]; + + if (savedInstanceState == null) { + signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID); + encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS); + preselectKeys(signatureKeyId, encryptionKeyIds); + } + } /** @@ -99,7 +104,7 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment { CachedPublicKeyRing keyring = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(signatureKeyId)); if (keyring.hasAnySecret()) { - mSignKeySpinner.setSelectedKeyId(signatureKeyId); + mSignKeySpinner.setPreSelectedKeyId(signatureKeyId); } } catch (PgpKeyNotFoundException e) { Log.e(Constants.TAG, "key not found!", e); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 460163a47..845b35512 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -98,7 +98,7 @@ public class CertifyKeySpinner extends KeySpinner { // - there are actually keys (not just "none" entry) // Then: // - select key that is capable of certifying, but only if there is only one key capable of it - if (mSelectedKeyId == Constants.key.none && mAdapter.getCount() > 1) { + if (mPreSelectedKeyId == Constants.key.none && mAdapter.getCount() > 1) { // preselect if key can certify int selection = -1; while (data.moveToNext()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index 579f37db2..ad1a14a33 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.ui.widget; +import android.annotation.SuppressLint; import android.content.Context; import android.database.Cursor; import android.graphics.Color; @@ -52,13 +53,13 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManager.LoaderCallbacks { public static final String ARG_SUPER_STATE = "super_state"; - public static final String ARG_SELECTED_KEY_ID = "select_key_id"; + public static final String ARG_KEY_ID = "key_id"; public interface OnKeyChangedListener { void onKeyChanged(long masterKeyId); } - protected long mSelectedKeyId = Constants.key.none; + protected long mPreSelectedKeyId = Constants.key.none; protected SelectKeyAdapter mAdapter = new SelectKeyAdapter(); protected OnKeyChangedListener mListener; @@ -85,17 +86,15 @@ public abstract class KeySpinner extends AppCompatSpinner implements super.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - mSelectedKeyId = id; if (mListener != null) { - mListener.onKeyChanged(mSelectedKeyId); + mListener.onKeyChanged(id); } } @Override public void onNothingSelected(AdapterView parent) { - mSelectedKeyId = Constants.key.none; if (mListener != null) { - mListener.onKeyChanged(mSelectedKeyId); + mListener.onKeyChanged(Constants.key.none); } } }); @@ -139,11 +138,11 @@ public abstract class KeySpinner extends AppCompatSpinner implements } public long getSelectedKeyId() { - return mSelectedKeyId; + return getSelectedItemId(); } - public void setSelectedKeyId(long selectedKeyId) { - mSelectedKeyId = selectedKeyId; + public void setPreSelectedKeyId(long selectedKeyId) { + mPreSelectedKeyId = selectedKeyId; } protected class SelectKeyAdapter extends BaseAdapter implements SpinnerAdapter { @@ -232,10 +231,10 @@ public abstract class KeySpinner extends AppCompatSpinner implements mIndexMasterKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID); mIndexCreationDate = newCursor.getColumnIndex(KeychainContract.KeyRings.CREATION); - // pre-select key if mSelectedKeyId is given - if (mSelectedKeyId != Constants.key.none && newCursor.moveToFirst()) { + // pre-select key if mPreSelectedKeyId is given + if (mPreSelectedKeyId != Constants.key.none && newCursor.moveToFirst()) { do { - if (newCursor.getLong(mIndexMasterKeyId) == mSelectedKeyId) { + if (newCursor.getLong(mIndexMasterKeyId) == mPreSelectedKeyId) { setSelection(newCursor.getPosition() + 1); } } while (newCursor.moveToNext()); @@ -260,6 +259,7 @@ public abstract class KeySpinner extends AppCompatSpinner implements return inner.getItemId(position - 1); } + @SuppressLint("ViewHolder") // inflate call is for the preview only @Override public View getView(int position, View convertView, ViewGroup parent) { try { @@ -304,4 +304,26 @@ public abstract class KeySpinner extends AppCompatSpinner implements return true; } + @Override + public void onRestoreInstanceState(Parcelable state) { + Bundle bundle = (Bundle) state; + + mPreSelectedKeyId = bundle.getLong(ARG_KEY_ID); + + // restore super state + super.onRestoreInstanceState(bundle.getParcelable(ARG_SUPER_STATE)); + + } + + @NonNull + @Override + public Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + + // save super state + bundle.putParcelable(ARG_SUPER_STATE, super.onSaveInstanceState()); + + bundle.putLong(ARG_KEY_ID, getSelectedKeyId()); + return bundle; + } } -- cgit v1.2.3 From 40ab96539c7658b18a0c4d95786f28fda1f69516 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 May 2015 22:33:14 +0200 Subject: move synchronous encryption into activity, and preserve checkbox state --- .../keychain/ui/EncryptActivity.java | 30 ++++++++++++++++++++-- .../keychain/ui/EncryptFilesFragment.java | 13 ++++------ .../keychain/ui/EncryptTextFragment.java | 5 ---- .../src/main/res/menu/encrypt_activity.xml | 9 +++++++ .../src/main/res/menu/encrypt_file_fragment.xml | 5 ---- .../src/main/res/menu/encrypt_text_fragment.xml | 5 ---- 6 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 OpenKeychain/src/main/res/menu/encrypt_activity.xml (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 9fd3a4988..4361705f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -21,6 +21,8 @@ import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; +import android.view.Menu; +import android.view.MenuItem; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -56,9 +58,33 @@ public class EncryptActivity extends BaseActivity { } } - public void toggleModeFragment() { - boolean symmetric = getModeFragment() instanceof EncryptModeAsymmetricFragment; + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.check_use_symmetric: { + item.setChecked(!item.isChecked()); + setModeFragment(item.isChecked()); + return true; + } + default: { + return super.onOptionsItemSelected(item); + } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.encrypt_activity, menu); + + Fragment frag = + getSupportFragmentManager().findFragmentById(R.id.encrypt_mode_container); + boolean isSymmetric = frag instanceof EncryptModeSymmetricFragment; + menu.findItem(R.id.check_use_symmetric).setChecked(isSymmetric); + + return super.onCreateOptionsMenu(menu); + } + private void setModeFragment(boolean symmetric) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.encrypt_mode_container, symmetric diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index fa35cc9ac..713c03fc2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -250,9 +250,6 @@ public class EncryptFilesFragment extends CryptoOperationFragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.isCheckable()) { - item.setChecked(!item.isChecked()); - } switch (item.getItemId()) { case R.id.encrypt_save: { encryptClicked(false); @@ -262,24 +259,24 @@ public class EncryptFilesFragment extends CryptoOperationFragment { encryptClicked(true); break; } - case R.id.check_use_symmetric: { - EncryptActivity encryptActivity = (EncryptActivity) getActivity(); - encryptActivity.toggleModeFragment(); - break; - } case R.id.check_use_armor: { + // we can NOT do this for every item, others might care! + item.setChecked(!item.isChecked()); mUseArmor = item.isChecked(); break; } case R.id.check_delete_after_encrypt: { + item.setChecked(!item.isChecked()); mDeleteAfterEncrypt = item.isChecked(); break; } case R.id.check_enable_compression: { + item.setChecked(!item.isChecked()); mUseCompression = item.isChecked(); break; } case R.id.check_encrypt_filenames: { + item.setChecked(!item.isChecked()); mEncryptFilenames = item.isChecked(); break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 89bc97e16..90eb2b1f3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -137,11 +137,6 @@ public class EncryptTextFragment extends CryptoOperationFragment { item.setChecked(!item.isChecked()); } switch (item.getItemId()) { - case R.id.check_use_symmetric: { - EncryptActivity modeInterface = (EncryptActivity) getActivity(); - modeInterface.toggleModeFragment(); - break; - } case R.id.check_enable_compression: { mUseCompression = item.isChecked(); break; diff --git a/OpenKeychain/src/main/res/menu/encrypt_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_activity.xml new file mode 100644 index 000000000..fdd19927e --- /dev/null +++ b/OpenKeychain/src/main/res/menu/encrypt_activity.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml index d6ed726fa..10928e4bb 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml @@ -14,11 +14,6 @@ android:icon="@drawable/ic_action_encrypt_share_24dp" app:showAsAction="always" /> - - - - Date: Wed, 27 May 2015 22:55:36 +0200 Subject: correctly preserve state in EncryptFilesFragment --- .../keychain/ui/EncryptFilesFragment.java | 43 ++++++++++++++++++---- .../keychain/ui/EncryptTextFragment.java | 2 + .../src/main/res/menu/encrypt_file_fragment.xml | 2 - 3 files changed, 38 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 713c03fc2..801f51b04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -72,19 +72,23 @@ import java.util.Set; public class EncryptFilesFragment extends CryptoOperationFragment { + public static final String ARG_DELETE_AFTER_ENCRYPT = "delete_after_encrypt"; + public static final String ARG_ENCRYPT_FILENAMES = "encrypt_filenames"; + public static final String ARG_USE_COMPRESSION = "use_compression"; public static final String ARG_USE_ASCII_ARMOR = "use_ascii_armor"; public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; - private boolean mUseArmor = false; - private boolean mUseCompression = true; - private boolean mDeleteAfterEncrypt = false; - private boolean mShareAfterEncrypt = false; - private boolean mEncryptFilenames = true; + private boolean mUseArmor; + private boolean mUseCompression; + private boolean mDeleteAfterEncrypt; + private boolean mEncryptFilenames; private boolean mHiddenRecipients = false; + private boolean mShareAfterEncrypt; + private ArrayList mOutputUris = new ArrayList<>(); private RecyclerView mSelectedFiles; @@ -136,19 +140,39 @@ public class EncryptFilesFragment extends CryptoOperationFragment { } }); - ArrayList inputUris = getArguments().getParcelableArrayList(ARG_URIS); + Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState; + + ArrayList inputUris = args.getParcelableArrayList(ARG_URIS); if (inputUris != null) { mFilesAdapter.addAll(inputUris); } - mUseArmor = getArguments().getBoolean(ARG_USE_ASCII_ARMOR); mSelectedFiles.setAdapter(mFilesAdapter); return view; } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putBoolean(ARG_DELETE_AFTER_ENCRYPT, mDeleteAfterEncrypt); + outState.putBoolean(ARG_USE_ASCII_ARMOR, mUseArmor); + outState.putBoolean(ARG_USE_COMPRESSION, mUseCompression); + outState.putBoolean(ARG_ENCRYPT_FILENAMES, mEncryptFilenames); + + outState.putParcelableArrayList(ARG_URIS, mFilesAdapter.getAsArrayList()); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState; + mDeleteAfterEncrypt = args.getBoolean(ARG_DELETE_AFTER_ENCRYPT, false); + mUseArmor = args.getBoolean(ARG_USE_ASCII_ARMOR, false); + mUseCompression = args.getBoolean(ARG_USE_COMPRESSION, true); + mEncryptFilenames = args.getBoolean(ARG_ENCRYPT_FILENAMES, true); + setHasOptionsMenu(true); } @@ -246,6 +270,11 @@ public class EncryptFilesFragment extends CryptoOperationFragment { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.encrypt_file_fragment, menu); + + menu.findItem(R.id.check_delete_after_encrypt).setChecked(mDeleteAfterEncrypt); + menu.findItem(R.id.check_use_armor).setChecked(mUseArmor); + menu.findItem(R.id.check_enable_compression).setChecked(mUseCompression); + menu.findItem(R.id.check_encrypt_filenames).setChecked(mEncryptFilenames); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 90eb2b1f3..7ca2bbb92 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -129,6 +129,8 @@ public class EncryptTextFragment extends CryptoOperationFragment { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.encrypt_text_fragment, menu); + + menu.findItem(R.id.check_enable_compression).setChecked(mUseCompression); } @Override diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml index 10928e4bb..54c6c2768 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml @@ -22,13 +22,11 @@ Date: Wed, 27 May 2015 23:03:04 +0200 Subject: correctly preserve state in EncryptTextFragment --- .../keychain/ui/EncryptTextFragment.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 7ca2bbb92..09f2365f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -56,9 +56,10 @@ import java.util.Set; public class EncryptTextFragment extends CryptoOperationFragment { public static final String ARG_TEXT = "text"; + public static final String ARG_USE_COMPRESSION = "use_compression"; - private boolean mShareAfterEncrypt = false; - private boolean mUseCompression = true; + private boolean mShareAfterEncrypt; + private boolean mUseCompression; private boolean mHiddenRecipients = false; private String mMessage = ""; @@ -117,10 +118,21 @@ public class EncryptTextFragment extends CryptoOperationFragment { return view; } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(ARG_USE_COMPRESSION, mUseCompression); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mMessage = getArguments().getString(ARG_TEXT); + if (savedInstanceState == null) { + mMessage = getArguments().getString(ARG_TEXT); + } + + Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState; + mUseCompression = args.getBoolean(ARG_USE_COMPRESSION, true); setHasOptionsMenu(true); } -- cgit v1.2.3 From 5c8af1c5a5ad4be2bf3f2f657fe3fbd2f1fe8a24 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 28 May 2015 02:27:44 +0200 Subject: don't show allowed key list if no key exists, and some minor PgpDecryptVerify changes --- .../operations/results/DecryptVerifyResult.java | 11 ++++--- .../operations/results/OperationResult.java | 2 +- .../keychain/pgp/PgpDecryptVerify.java | 37 ++++++++++++++-------- .../keychain/remote/OpenPgpService.java | 19 +++++------ OpenKeychain/src/main/res/values-de/strings.xml | 2 +- OpenKeychain/src/main/res/values-es/strings.xml | 2 +- OpenKeychain/src/main/res/values-fr/strings.xml | 2 +- OpenKeychain/src/main/res/values-ja/strings.xml | 2 +- OpenKeychain/src/main/res/values-nl/strings.xml | 2 +- OpenKeychain/src/main/res/values-sr/strings.xml | 2 +- .../src/main/res/values-zh-rTW/strings.xml | 2 +- OpenKeychain/src/main/res/values/strings.xml | 2 +- 12 files changed, 50 insertions(+), 35 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java index 917b3415f..7680107f8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java @@ -27,12 +27,19 @@ import org.sufficientlysecure.keychain.util.Passphrase; public class DecryptVerifyResult extends InputPendingResult { + public static final int RESULT_NO_DATA = RESULT_ERROR + 16; + public static final int RESULT_KEY_DISALLOWED = RESULT_ERROR + 32; + OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; // This holds the charset which was specified in the ascii armor, if specified // https://tools.ietf.org/html/rfc4880#page56 String mCharset; + public boolean isKeysDisallowed () { + return (mResult & RESULT_KEY_DISALLOWED) == RESULT_KEY_DISALLOWED; + } + public OpenPgpSignatureResult getSignatureResult() { return mSignatureResult; } @@ -57,10 +64,6 @@ public class DecryptVerifyResult extends InputPendingResult { mCharset = charset; } - public boolean isPending() { - return (mResult & RESULT_PENDING) == RESULT_PENDING; - } - public DecryptVerifyResult(int result, OperationLog log) { super(result, log); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index ad7feaea6..119678f16 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -590,7 +590,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_ERROR_EXTRACT_KEY (LogLevel.ERROR, R.string.msg_dc_error_extract_key), MSG_DC_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_dc_error_integrity_check), MSG_DC_ERROR_INTEGRITY_MISSING (LogLevel.ERROR, R.string.msg_dc_error_integrity_missing), - MSG_DC_ERROR_INVALID_SIGLIST(LogLevel.ERROR, R.string.msg_dc_error_invalid_siglist), + MSG_DC_ERROR_INVALID_DATA (LogLevel.ERROR, R.string.msg_dc_error_invalid_data), MSG_DC_ERROR_IO (LogLevel.ERROR, R.string.msg_dc_error_io), MSG_DC_ERROR_NO_DATA (LogLevel.ERROR, R.string.msg_dc_error_no_data), MSG_DC_ERROR_NO_KEY (LogLevel.ERROR, R.string.msg_dc_error_no_key), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index f6580b85a..aa1125800 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -384,7 +384,7 @@ public class PgpDecryptVerify extends BaseOperation { } if (enc == null) { - log.add(LogType.MSG_DC_ERROR_INVALID_SIGLIST, indent); + log.add(LogType.MSG_DC_ERROR_INVALID_DATA, indent); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -419,6 +419,7 @@ public class PgpDecryptVerify extends BaseOperation { } Passphrase passphrase = null; + boolean skippedDisallowedKey = false; // go through all objects and find one we can decrypt while (it.hasNext()) { @@ -451,13 +452,6 @@ public class PgpDecryptVerify extends BaseOperation { log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1); continue; } - // get subkey which has been used for this encryption packet - secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId); - if (secretEncryptionKey == null) { - // should actually never happen, so no need to be more specific. - log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1); - continue; - } // allow only specific keys for decryption? if (mAllowedKeyIds != null) { @@ -469,11 +463,20 @@ public class PgpDecryptVerify extends BaseOperation { if (!mAllowedKeyIds.contains(masterKeyId)) { // this key is in our db, but NOT allowed! // continue with the next packet in the while loop + skippedDisallowedKey = true; log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent + 1); continue; } } + // get subkey which has been used for this encryption packet + secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId); + if (secretEncryptionKey == null) { + // should actually never happen, so no need to be more specific. + log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1); + continue; + } + /* secret key exists in database and is allowed! */ asymmetricPacketFound = true; @@ -604,10 +607,18 @@ public class PgpDecryptVerify extends BaseOperation { } encryptedData = encryptedDataAsymmetric; } else { - // If we didn't find any useful data, error out + // there wasn't even any useful data + if (!anyPacketFound) { + log.add(LogType.MSG_DC_ERROR_NO_DATA, indent + 1); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_NO_DATA, log); + } + // there was data but key wasn't allowed + if (skippedDisallowedKey) { + log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_KEY_DISALLOWED, log); + } // no packet has been found where we have the corresponding secret key in our db - log.add( - anyPacketFound ? LogType.MSG_DC_ERROR_NO_KEY : LogType.MSG_DC_ERROR_NO_DATA, indent + 1); + log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -910,7 +921,7 @@ public class PgpDecryptVerify extends BaseOperation { PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); if (sigList == null) { - log.add(LogType.MSG_DC_ERROR_INVALID_SIGLIST, 0); + log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -993,7 +1004,7 @@ public class PgpDecryptVerify extends BaseOperation { } else if (o instanceof PGPSignatureList) { sigList = (PGPSignatureList) o; } else { - log.add(LogType.MSG_DC_ERROR_INVALID_SIGLIST, 0); + log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 4a8bf9332..179b78f26 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -34,7 +34,6 @@ import org.openintents.openpgp.util.OpenPgpApi; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.pgp.PgpConstants; @@ -601,9 +600,8 @@ public class OpenPgpService extends RemoteService { result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); return result; } else { - LogEntryParcel errorMsg = pgpResult.getLog().getLast(); - - if (errorMsg.mType == OperationResult.LogType.MSG_DC_ERROR_NO_KEY) { + // + if (pgpResult.isKeysDisallowed()) { // allow user to select allowed keys Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_INTENT, getSelectAllowedKeysIntent(data)); @@ -611,14 +609,17 @@ public class OpenPgpService extends RemoteService { return result; } - throw new Exception(getString(errorMsg.mType.getMsgId())); + String errorMsg = getString(pgpResult.getLog().getLast().mType.getMsgId()); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.GENERIC_ERROR, errorMsg)); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + return result; } - } catch (Exception e) { - Log.d(Constants.TAG, "decryptAndVerifyImpl", e); + } catch (IOException e) { + Log.e(Constants.TAG, "decryptAndVerifyImpl", e); Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_ERROR, - new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); + result.putExtra(OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); return result; } finally { diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml index 4fd310837..2dc6962cb 100644 --- a/OpenKeychain/src/main/res/values-de/strings.xml +++ b/OpenKeychain/src/main/res/values-de/strings.xml @@ -929,7 +929,7 @@ Unbekannter Fehler bei Schlüsselentsperrung! Integritätsprüfungsfehler! Fehlende Integritätsprüfung Dies kann passieren, wenn die Verschlüsselungsanwendung veraltet ist oder durch einen Downgrade-Angriff. - Keine gültigen Signaturdaten gefunden! + Keine gültigen Signaturdaten gefunden! Ein-/Ausgabefehler während Vorgang aufgetreten! Keine verschlüsselten Daten in Datenstrom gefunden! Keine verschlüsselten Daten mit bekanntem geheimen Schlüssel in Datenstrom gefunden! diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml index 2d94eb6a2..f672ab84b 100644 --- a/OpenKeychain/src/main/res/values-es/strings.xml +++ b/OpenKeychain/src/main/res/values-es/strings.xml @@ -928,7 +928,7 @@ ¡Error desconocido al desbloquear clave! ¡Error de comprobación de integridad! ¡Verificación de integridad ausente! Esto puede ocurrir porque la aplicación de cifrado no está actualizada, o debido a un ataque desactualización. - ¡No se encontraron datos de firma válidos! + ¡No se encontraron datos de firma válidos! ¡Se encontró Excepción de E/S durante la operación! ¡No se encontraron datos cifrados en el flujo de datos (`stream`)! ¡No se encontraron datos cifrados con clave secreta (privada) conocida en el flujo de datos (`stream`)! diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml index f34dd8e46..c7ac082dd 100644 --- a/OpenKeychain/src/main/res/values-fr/strings.xml +++ b/OpenKeychain/src/main/res/values-fr/strings.xml @@ -928,7 +928,7 @@ Erreur inconnue de déverrouillage de la clef ! Erreur de vérification de l\'intégrité ! Vérification de l\'intégrité absente ! Ceci peut arriver car l\'application n\'est pas à jour, ou à cause d\'une attaque par mise à niveau inférieur. - Aucune donnée de signature valide trouvée ! + Aucune donnée de signature valide trouvée ! Une exception E/S a été rencontrée durant l\'opération ! Aucune donnée chiffrée n\'a été trouvée dans le flux ! Aucune donnée chiffrée avec une clef secrète connue n\'a été trouvée dans le flux ! diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml index 13647a1bb..ad66b9a37 100644 --- a/OpenKeychain/src/main/res/values-ja/strings.xml +++ b/OpenKeychain/src/main/res/values-ja/strings.xml @@ -913,7 +913,7 @@ 鍵のロック解除で不明なエラー! 完全性チェックエラー! 完全聖チェックの欠落!これは暗号化アプリケーションが期限切れになった場合、もしくは暗号強度低下攻撃がある場合に発生します。 - 正常な署名データが見付からなかった! + 正常な署名データが見付からなかった! 操作中にIO例外に当たりました! ストリーム中に暗号化されたデータが見付からなかった! ストリーム中に既知の秘密鍵で暗号化されたデータが見付からなかった! diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml index 74e2c7117..37975ab1a 100644 --- a/OpenKeychain/src/main/res/values-nl/strings.xml +++ b/OpenKeychain/src/main/res/values-nl/strings.xml @@ -928,7 +928,7 @@ Onbekende fout bij ontgrendelen van sleutel! Fout bij integriteitscontrole! Integriteitscheck ontbreekt! Dit kan gebeuren omdat de versleutelingsapplicatie verouderd is, of door een downgrade-aanval. - Geen geldige ondertekeningsgegevens gevonden! + Geen geldige ondertekeningsgegevens gevonden! I/O-uitzondering tegengekomen tijdens bewerking! Geen versleutelde gegevens gevonden! Geen versleutelde gegevens met bekende geheime sleutel gevonden! diff --git a/OpenKeychain/src/main/res/values-sr/strings.xml b/OpenKeychain/src/main/res/values-sr/strings.xml index c4c92dce5..5b3027398 100644 --- a/OpenKeychain/src/main/res/values-sr/strings.xml +++ b/OpenKeychain/src/main/res/values-sr/strings.xml @@ -915,7 +915,7 @@ Непозната грешка откључавања кључа! Грешка провере интегритета! Недостаје провера интегритета! Ово може да се деси ако је апликација за шифровање застарела, или услед напада старијег издања. - Нису нађени исправни подаци потписа! + Нису нађени исправни подаци потписа! Наиђох на У/И изузетак током радње! Шифровани подаци нису нађени у току! Подаци шифровани познатим тајним кључем нису нађени у току! diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml index 95fa8a28c..728eeccdd 100644 --- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml +++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml @@ -510,7 +510,7 @@ 找不到金鑰! - 找不到有效的簽名資訊! + 找不到有效的簽名資訊! 開始解密… diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index f01b2cace..3ae4afa35 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1041,7 +1041,7 @@ "Unknown error unlocking key!" "Integrity check error!" "Missing integrity check! This can happen because the encrypting application is out of date, or from a downgrade attack." - "No valid signature data found!" + "No valid OpenPGP encrypted or signed data found!" "Encountered IO Exception during operation!" "No encrypted data found in stream!" "No encrypted data with known secret key found in stream!" -- cgit v1.2.3 From eb830c6786c500d69ce2a06203b7cf336ae8a9bf Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 28 May 2015 11:40:35 +0200 Subject: warn on signature earlier than key creation, err on significantly earlier --- .../operations/results/OperationResult.java | 1 + .../keychain/pgp/UncachedKeyRing.java | 21 +++++++++++++++++++++ OpenKeychain/src/main/res/values/strings.xml | 1 + 3 files changed, 23 insertions(+) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 119678f16..1cbff8a0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -401,6 +401,7 @@ public abstract class OperationResult implements Parcelable { MSG_KC_SUB_BAD_LOCAL(LogLevel.WARN, R.string.msg_kc_sub_bad_local), MSG_KC_SUB_BAD_KEYID(LogLevel.WARN, R.string.msg_kc_sub_bad_keyid), MSG_KC_SUB_BAD_TIME(LogLevel.WARN, R.string.msg_kc_sub_bad_time), + MSG_KC_SUB_BAD_TIME_EARLY(LogLevel.WARN, R.string.msg_kc_sub_bad_time_early), MSG_KC_SUB_BAD_TYPE(LogLevel.WARN, R.string.msg_kc_sub_bad_type), MSG_KC_SUB_DUP (LogLevel.DEBUG, R.string.msg_kc_sub_dup), MSG_KC_SUB_PRIMARY_BAD(LogLevel.WARN, R.string.msg_kc_sub_primary_bad), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 2bb4f7dc4..ecf68890e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -820,6 +820,15 @@ public class UncachedKeyRing { continue; } + Date keyCreationTime = key.getCreationTime(), keyCreationTimeLenient; + { + Calendar keyCreationCal = Calendar.getInstance(); + keyCreationCal.setTime(keyCreationTime); + // allow for diverging clocks up to one day when checking creation time + keyCreationCal.add(Calendar.MINUTE, -5); + keyCreationTimeLenient = keyCreationCal.getTime(); + } + // A subkey needs exactly one subkey binding certificate, and optionally one revocation // certificate. PGPPublicKey modified = key; @@ -851,6 +860,18 @@ public class UncachedKeyRing { continue; } + if (cert.getCreationTime().before(keyCreationTime)) { + // Signature is earlier than key creation time + log.add(LogType.MSG_KC_SUB_BAD_TIME_EARLY, indent); + // due to an earlier accident, we generated keys which had creation timestamps + // a few seconds after their signature timestamp. for compatibility, we only + // error out with some margin of error + if (cert.getCreationTime().before(keyCreationTimeLenient)) { + badCerts += 1; + continue; + } + } + if (cert.isLocal()) { // Creation date in the future? No way! log.add(LogType.MSG_KC_SUB_BAD_LOCAL, indent); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 3ae4afa35..d2563a38b 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -829,6 +829,7 @@ "Removing subkey binding certificate with 'local' flag" "Subkey binding issuer id mismatch" "Removing subkey binding certificate with future timestamp" + "Subkey binding certificate has earlier timestamp than its key!" "Unknown subkey certificate type: %s" "Removing redundant subkey binding certificate" "Removing subkey binding certificate due to invalid primary binding certificate" -- cgit v1.2.3 From 8de0d9e6da63c6755b86c6b9850def057e4bd8c0 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 28 May 2015 14:41:26 +0200 Subject: create keys with fixed timestamp --- .../sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 2f771d8f2..991d013ae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -151,7 +151,7 @@ public class PgpKeyOperation { } /** Creates new secret key. */ - private PGPKeyPair createKey(SubkeyAdd add, OperationLog log, int indent) { + private PGPKeyPair createKey(SubkeyAdd add, Date creationTime, OperationLog log, int indent) { try { // Some safety checks @@ -249,7 +249,7 @@ public class PgpKeyOperation { } // build new key pair - return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); + return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), creationTime); } catch(NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e); @@ -295,8 +295,10 @@ public class PgpKeyOperation { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } + Date creationTime = new Date(); + subProgressPush(10, 30); - PGPKeyPair keyPair = createKey(add, log, indent); + PGPKeyPair keyPair = createKey(add, creationTime, log, indent); subProgressPop(); // return null if this failed (an error will already have been logged by createKey) @@ -323,8 +325,8 @@ public class PgpKeyOperation { masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); subProgressPush(50, 100); - CryptoInputParcel cryptoInput = new CryptoInputParcel(new Date(), new Passphrase("")); - return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log); + CryptoInputParcel cryptoInput = new CryptoInputParcel(creationTime, new Passphrase("")); + return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log, indent); } catch (PGPException e) { log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent); @@ -900,7 +902,7 @@ public class PgpKeyOperation { (i-1) * (100 / saveParcel.mAddSubKeys.size()), i * (100 / saveParcel.mAddSubKeys.size()) ); - PGPKeyPair keyPair = createKey(add, log, indent); + PGPKeyPair keyPair = createKey(add, cryptoInput.getSignatureTime(), log, indent); subProgressPop(); if (keyPair == null) { log.add(LogType.MSG_MF_ERROR_PGP, indent +1); -- cgit v1.2.3 From ee02e110e7f1a90d2a91c4fc09834b8c073cbba7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 28 May 2015 15:02:50 +0200 Subject: don't keep an activity reference in CreateKeyFinalFragment --- .../keychain/ui/CreateKeyFinalFragment.java | 44 ++++++++++------------ 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'OpenKeychain/src/main') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index b0a13c897..bdb534757 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -54,8 +54,6 @@ public class CreateKeyFinalFragment extends Fragment { public static final int REQUEST_EDIT_KEY = 0x00008007; - CreateKeyActivity mCreateKeyActivity; - TextView mNameEdit; TextView mEmailEdit; CheckBox mUploadCheckbox; @@ -66,9 +64,6 @@ public class CreateKeyFinalFragment extends Fragment { SaveKeyringParcel mSaveKeyringParcel; - /** - * Creates new instance of this fragment - */ public static CreateKeyFinalFragment newInstance() { CreateKeyFinalFragment frag = new CreateKeyFinalFragment(); @@ -90,11 +85,13 @@ public class CreateKeyFinalFragment extends Fragment { mEditText = (TextView) view.findViewById(R.id.create_key_edit_text); mEditButton = view.findViewById(R.id.create_key_edit_button); + CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity(); + // set values - mNameEdit.setText(mCreateKeyActivity.mName); - if (mCreateKeyActivity.mAdditionalEmails != null && mCreateKeyActivity.mAdditionalEmails.size() > 0) { - String emailText = mCreateKeyActivity.mEmail + ", "; - Iterator it = mCreateKeyActivity.mAdditionalEmails.iterator(); + mNameEdit.setText(createKeyActivity.mName); + if (createKeyActivity.mAdditionalEmails != null && createKeyActivity.mAdditionalEmails.size() > 0) { + String emailText = createKeyActivity.mEmail + ", "; + Iterator it = createKeyActivity.mAdditionalEmails.iterator(); while (it.hasNext()) { Object next = it.next(); emailText += next; @@ -104,7 +101,7 @@ public class CreateKeyFinalFragment extends Fragment { } mEmailEdit.setText(emailText); } else { - mEmailEdit.setText(mCreateKeyActivity.mEmail); + mEmailEdit.setText(createKeyActivity.mEmail); } mCreateButton.setOnClickListener(new View.OnClickListener() { @@ -117,7 +114,10 @@ public class CreateKeyFinalFragment extends Fragment { mBackButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT); + CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity(); + if (createKeyActivity != null) { + createKeyActivity.loadFragment(null, FragAction.TO_LEFT); + } } }); @@ -133,12 +133,6 @@ public class CreateKeyFinalFragment extends Fragment { return view; } - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mCreateKeyActivity = (CreateKeyActivity) getActivity(); - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -159,7 +153,7 @@ public class CreateKeyFinalFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mCreateKeyActivity = (CreateKeyActivity) getActivity(); + CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity(); if (mSaveKeyringParcel == null) { mSaveKeyringParcel = new SaveKeyringParcel(); @@ -170,21 +164,21 @@ public class CreateKeyFinalFragment extends Fragment { mSaveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); String userId = KeyRing.createUserId( - new KeyRing.UserId(mCreateKeyActivity.mName, mCreateKeyActivity.mEmail, null) + new KeyRing.UserId(createKeyActivity.mName, createKeyActivity.mEmail, null) ); mSaveKeyringParcel.mAddUserIds.add(userId); mSaveKeyringParcel.mChangePrimaryUserId = userId; - if (mCreateKeyActivity.mAdditionalEmails != null - && mCreateKeyActivity.mAdditionalEmails.size() > 0) { - for (String email : mCreateKeyActivity.mAdditionalEmails) { + if (createKeyActivity.mAdditionalEmails != null + && createKeyActivity.mAdditionalEmails.size() > 0) { + for (String email : createKeyActivity.mAdditionalEmails) { String thisUserId = KeyRing.createUserId( - new KeyRing.UserId(mCreateKeyActivity.mName, email, null) + new KeyRing.UserId(createKeyActivity.mName, email, null) ); mSaveKeyringParcel.mAddUserIds.add(thisUserId); } } - mSaveKeyringParcel.mNewUnlock = mCreateKeyActivity.mPassphrase != null - ? new ChangeUnlockParcel(mCreateKeyActivity.mPassphrase, null) + mSaveKeyringParcel.mNewUnlock = createKeyActivity.mPassphrase != null + ? new ChangeUnlockParcel(createKeyActivity.mPassphrase, null) : null; } } -- cgit v1.2.3