aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2014-09-02 01:24:16 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2014-09-02 01:24:16 +0200
commite0905a3afbba7f96822becb378b7e8fd9c51e85a (patch)
tree72f463174e322bea66c7702c236739a196b6514d /OpenKeychain/src/main/java/org
parenta97ebc1ec9afa4951f676b4483c6db871c4704ab (diff)
downloadopen-keychain-e0905a3afbba7f96822becb378b7e8fd9c51e85a.tar.gz
open-keychain-e0905a3afbba7f96822becb378b7e8fd9c51e85a.tar.bz2
open-keychain-e0905a3afbba7f96822becb378b7e8fd9c51e85a.zip
cache key s2k type in database, for later use
Diffstat (limited to 'OpenKeychain/src/main/java/org')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java45
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java23
7 files changed, 105 insertions, 36 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 51770f930..833e1ad3d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -80,6 +80,59 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
return (CanonicalizedSecretKeyRing) mRing;
}
+ public enum SecretKeyType {
+ UNAVAILABLE(0), GNU_DUMMY (1), PASSPHRASE (2), PASSPHRASE_EMPTY (3), DIVERT_TO_CARD (4);
+
+ final int mNum;
+ SecretKeyType(int num) {
+ mNum = num;
+ }
+
+ public static SecretKeyType fromNum(int num) {
+ switch (num) {
+ case 1: return GNU_DUMMY;
+ case 2: return PASSPHRASE;
+ case 3: return PASSPHRASE_EMPTY;
+ case 4: return DIVERT_TO_CARD;
+ // if this case happens, it's probably a check from a database value
+ default: return UNAVAILABLE;
+ }
+ }
+
+ public int getNum() {
+ return mNum;
+ }
+
+ public boolean isUsable() {
+ return this != UNAVAILABLE && this != GNU_DUMMY;
+ }
+
+ }
+
+ public SecretKeyType getSecretKeyType() {
+ if (mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K) {
+ // divert to card is special
+ if (mSecretKey.getS2K().getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) {
+ return SecretKeyType.DIVERT_TO_CARD;
+ }
+ // no matter the exact protection mode, it's some kind of dummy key
+ return SecretKeyType.GNU_DUMMY;
+ }
+
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
+ // If this doesn't throw
+ mSecretKey.extractPrivateKey(keyDecryptor);
+ // It means the passphrase is empty
+ return SecretKeyType.PASSPHRASE_EMPTY;
+ } catch (PGPException e) {
+ // Otherwise, it's just a regular ol' passphrase
+ return SecretKeyType.PASSPHRASE;
+ }
+
+ }
+
/**
* Returns true on right passphrase
*/
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
index d8b873d31..48a2aaeb6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
@@ -74,19 +74,6 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
return new CanonicalizedSecretKey(this, mRing.getSecretKey(id));
}
- public HashSet<Long> getAvailableSubkeys() {
- HashSet<Long> result = new HashSet<Long>();
- // then, mark exactly the keys we have available
- for (PGPSecretKey sub : new IterableIterator<PGPSecretKey>(getRing().getSecretKeys())) {
- S2K s2k = sub.getS2K();
- // add key, except if the private key has been stripped (GNU extension)
- if(s2k == null || (s2k.getProtectionMode() != S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY)) {
- result.add(sub.getKeyID());
- }
- }
- return result;
- }
-
/** Getter that returns the subkey that should be used for signing. */
CanonicalizedSecretKey getSigningSubKey() throws PgpGeneralException {
PGPSecretKey key = mRing.getSecretKey(getSignId());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 4fde8e581..e1dae55ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -34,6 +34,8 @@ import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
@@ -592,27 +594,40 @@ public class ProviderHelper {
values.put(Keys.HAS_SECRET, 0);
mContentResolver.update(uri, values, null, null);
- values.put(Keys.HAS_SECRET, 1);
// then, mark exactly the keys we have available
log(LogLevel.INFO, LogType.MSG_IS_IMPORTING_SUBKEYS);
mIndent += 1;
- Set<Long> available = keyRing.getAvailableSubkeys();
- for (UncachedPublicKey sub : keyRing.publicKeyIterator()) {
+ for (CanonicalizedSecretKey sub : keyRing.secretKeyIterator()) {
long id = sub.getKeyId();
- if (available.contains(id)) {
- int upd = mContentResolver.update(uri, values, Keys.KEY_ID + " = ?",
- new String[]{Long.toString(id)});
- if (upd == 1) {
- log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK,
- PgpKeyHelper.convertKeyIdToHex(id)
- );
- } else {
- log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT,
- PgpKeyHelper.convertKeyIdToHex(id)
- );
+ SecretKeyType mode = sub.getSecretKeyType();
+ values.put(Keys.HAS_SECRET, mode.getNum());
+ int upd = mContentResolver.update(uri, values, Keys.KEY_ID + " = ?",
+ new String[]{ Long.toString(id) });
+ if (upd == 1) {
+ switch (mode) {
+ case PASSPHRASE:
+ log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK,
+ PgpKeyHelper.convertKeyIdToHex(id)
+ );
+ break;
+ case PASSPHRASE_EMPTY:
+ log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_EMPTY,
+ PgpKeyHelper.convertKeyIdToHex(id)
+ );
+ break;
+ case GNU_DUMMY:
+ log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_STRIPPED,
+ PgpKeyHelper.convertKeyIdToHex(id)
+ );
+ break;
+ case DIVERT_TO_CARD:
+ log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_DIVERT,
+ PgpKeyHelper.convertKeyIdToHex(id)
+ );
+ break;
}
} else {
- log(LogLevel.INFO, LogType.MSG_IS_SUBKEY_STRIPPED,
+ log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT,
PgpKeyHelper.convertKeyIdToHex(id)
);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
index 4e89d0243..438443644 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
@@ -287,6 +287,8 @@ public class OperationResultParcel implements Parcelable {
MSG_IS_SUBKEY_NONEXISTENT (R.string.msg_is_subkey_nonexistent),
MSG_IS_SUBKEY_OK (R.string.msg_is_subkey_ok),
MSG_IS_SUBKEY_STRIPPED (R.string.msg_is_subkey_stripped),
+ MSG_IS_SUBKEY_DIVERT (R.string.msg_is_subkey_divert),
+ MSG_IS_SUBKEY_EMPTY (R.string.msg_is_subkey_empty),
MSG_IS_SUCCESS_IDENTICAL (R.string.msg_is_success_identical),
MSG_IS_SUCCESS (R.string.msg_is_success),
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
index 9ddc8e3e1..3f1053f69 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
@@ -32,6 +32,7 @@ import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
@@ -190,7 +191,7 @@ public class SelectSecretKeyFragment extends ListFragment implements
if(mFilterCertify) {
// Only enable if can certify
if (cursor.getInt(mIndexCanCertify) == 0
- || cursor.getInt(mIndexHasSecret) == 0) {
+ || !SecretKeyType.fromNum(cursor.getInt(mIndexHasSecret)).isUsable()) {
h.status.setText(R.string.can_certify_not);
} else {
h.status.setText(R.string.can_certify);
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 08300ff04..5d8e13349 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -300,7 +300,7 @@ public class ViewKeyActivity extends ActionBarActivity implements
exportHelper.showExportKeysDialog(
new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
- Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) == 1)
+ Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index 489cbcefb..7dd61117c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -31,6 +31,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
@@ -113,7 +114,8 @@ public class SubkeysAdapter extends CursorAdapter {
hasAnySecret = false;
if (newCursor != null && newCursor.moveToFirst()) {
do {
- if (newCursor.getInt(INDEX_HAS_SECRET) != 0) {
+ SecretKeyType hasSecret = SecretKeyType.fromNum(newCursor.getInt(INDEX_HAS_SECRET));
+ if (hasSecret.isUsable()) {
hasAnySecret = true;
break;
}
@@ -149,12 +151,21 @@ public class SubkeysAdapter extends CursorAdapter {
vKeyId.setText(keyIdStr);
// may be set with additional "stripped" later on
- if (hasAnySecret && cursor.getInt(INDEX_HAS_SECRET) == 0) {
- vKeyDetails.setText(algorithmStr + ", " +
- context.getString(R.string.key_stripped));
- } else {
- vKeyDetails.setText(algorithmStr);
+ switch (SecretKeyType.fromNum(cursor.getInt(INDEX_HAS_SECRET))) {
+ case GNU_DUMMY:
+ algorithmStr += ", " + context.getString(R.string.key_stripped);
+ break;
+ case DIVERT_TO_CARD:
+ algorithmStr += ", " + context.getString(R.string.key_divert);
+ break;
+ case PASSPHRASE_EMPTY:
+ algorithmStr += ", " + context.getString(R.string.key_no_passphrase);
+ break;
+ case UNAVAILABLE:
+ algorithmStr += ", " + context.getString(R.string.key_unavailable);
+ break;
}
+ vKeyDetails.setText(algorithmStr);
boolean isMasterKey = cursor.getInt(INDEX_RANK) == 0;
if (isMasterKey) {