aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2013-03-22 14:16:49 +0100
committerDominik Schürmann <dominik@dominikschuermann.de>2013-03-22 14:16:49 +0100
commit30fa184e7e6a3bbd1a26c39ef5c3037dcbe3ea32 (patch)
treec9d47233a0486e3e05e882e05d60202f5565b135 /OpenPGP-Keychain
parentbee5075f56173b7bd05b210c778c846d154b2ee9 (diff)
parent0075c522a6773c14e34875cc7118055cde2e13be (diff)
downloadopen-keychain-30fa184e7e6a3bbd1a26c39ef5c3037dcbe3ea32.tar.gz
open-keychain-30fa184e7e6a3bbd1a26c39ef5c3037dcbe3ea32.tar.bz2
open-keychain-30fa184e7e6a3bbd1a26c39ef5c3037dcbe3ea32.zip
Merge with ashh87s pull request
Diffstat (limited to 'OpenPGP-Keychain')
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/certify_small.pngbin0 -> 2091 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi/certify_small.pngbin0 -> 1401 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/certify_small.pngbin0 -> 1401 bytes
-rw-r--r--OpenPGP-Keychain/res/layout/edit_key_section.xml3
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_child_item.xml8
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_editor.xml4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpHelper.java118
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java49
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java1
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java1
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java55
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java14
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java12
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java15
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java5
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java14
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java5
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java11
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java3
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java70
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java8
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java15
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java15
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java10
28 files changed, 392 insertions, 61 deletions
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/certify_small.png b/OpenPGP-Keychain/res/drawable-hdpi/certify_small.png
new file mode 100644
index 000000000..9e54464ed
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-hdpi/certify_small.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi/certify_small.png b/OpenPGP-Keychain/res/drawable-mdpi/certify_small.png
new file mode 100644
index 000000000..575b2d866
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-mdpi/certify_small.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/certify_small.png b/OpenPGP-Keychain/res/drawable/certify_small.png
new file mode 100644
index 000000000..575b2d866
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable/certify_small.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/layout/edit_key_section.xml b/OpenPGP-Keychain/res/layout/edit_key_section.xml
index 870e1b063..dd0a5d4bd 100644
--- a/OpenPGP-Keychain/res/layout/edit_key_section.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_section.xml
@@ -41,6 +41,7 @@
android:text="Section Name" />
<ImageView
+ android:id="@+id/plusbutton"
style="@style/PlusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -54,4 +55,4 @@
android:orientation="vertical"
android:paddingBottom="6dip" />
-</org.sufficientlysecure.keychain.ui.widget.SectionView> \ No newline at end of file
+</org.sufficientlysecure.keychain.ui.widget.SectionView>
diff --git a/OpenPGP-Keychain/res/layout/key_list_child_item.xml b/OpenPGP-Keychain/res/layout/key_list_child_item.xml
index 868989cf6..81d843529 100644
--- a/OpenPGP-Keychain/res/layout/key_list_child_item.xml
+++ b/OpenPGP-Keychain/res/layout/key_list_child_item.xml
@@ -64,6 +64,12 @@
android:paddingTop="2dip" >
<ImageView
+ android:id="@+id/ic_certifyKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/certify_small" />
+
+ <ImageView
android:id="@+id/ic_encryptKey"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -93,4 +99,4 @@
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/OpenPGP-Keychain/res/layout/key_server_editor.xml b/OpenPGP-Keychain/res/layout/key_server_editor.xml
index e4c25b316..51ff8a663 100644
--- a/OpenPGP-Keychain/res/layout/key_server_editor.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_editor.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<org.thialfihar.android.apg.ui.widget.KeyServerEditor
+<org.sufficientlysecure.keychain.ui.widget.KeyServerEditor
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -49,4 +49,4 @@
android:layout_height="1dip"
android:background="?android:attr/listDivider"/>
-</org.thialfihar.android.apg.ui.widget.KeyServerEditor>
+</org.sufficientlysecure.keychain.ui.widget.KeyServerEditor>
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpHelper.java
index f59bd58de..810f3a6f2 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpHelper.java
@@ -24,12 +24,16 @@ import java.util.Locale;
import java.util.Vector;
import org.spongycastle.bcpg.sig.KeyFlags;
+import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
+import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
+import org.spongycastle.openpgp.PGPException;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.IterableIterator;
@@ -77,6 +81,22 @@ public class PgpHelper {
}
@SuppressWarnings("unchecked")
+ public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
+ long cnt = 0;
+ if (keyRing == null) {
+ return null;
+ }
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (cnt == num) {
+ return key;
+ }
+ cnt++;
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
@@ -102,6 +122,19 @@ public class PgpHelper {
return signingKeys;
}
+ @SuppressWarnings("unchecked")
+ public static Vector<PGPSecretKey> getCertificationKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
+
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (isCertificationKey(key)) {
+ signingKeys.add(key);
+ }
+ }
+
+ return signingKeys;
+ }
+
public static Vector<PGPPublicKey> getUsableEncryptKeys(PGPPublicKeyRing keyRing) {
Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>();
Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing);
@@ -137,6 +170,24 @@ public class PgpHelper {
return isExpired(key.getPublicKey());
}
+ public static Vector<PGPSecretKey> getUsableCertificationKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
+ Vector<PGPSecretKey> signingKeys = getCertificationKeys(keyRing);
+ PGPSecretKey masterKey = null;
+ for (int i = 0; i < signingKeys.size(); ++i) {
+ PGPSecretKey key = signingKeys.get(i);
+ if (key.isMasterKey()) {
+ masterKey = key;
+ } else {
+ usableKeys.add(key);
+ }
+ }
+ if (masterKey != null) {
+ usableKeys.add(masterKey);
+ }
+ return usableKeys;
+ }
+
public static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) {
Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
@@ -188,6 +239,19 @@ public class PgpHelper {
return encryptKeys.get(0);
}
+ public static PGPSecretKey getCertificationKey(Context context, long masterKeyId) {
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
+ masterKeyId);
+ if (keyRing == null) {
+ return null;
+ }
+ Vector<PGPSecretKey> signingKeys = getUsableCertificationKeys(keyRing);
+ if (signingKeys.size() == 0) {
+ return null;
+ }
+ return signingKeys.get(0);
+ }
+
public static PGPSecretKey getSigningKey(Context context, long masterKeyId) {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
masterKeyId);
@@ -313,6 +377,36 @@ public class PgpHelper {
return isSigningKey(key.getPublicKey());
}
+ @SuppressWarnings("unchecked")
+ public static boolean isCertificationKey(PGPPublicKey key) {
+ if (key.getVersion() <= 3) {
+ return true;
+ }
+
+ for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
+ continue;
+ }
+ PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
+
+ if (hashed != null && (hashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
+ return true;
+ }
+
+ PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
+
+ if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean isCertificationKey(PGPSecretKey key) {
+ return isCertificationKey(key.getPublicKey());
+ }
+
public static String getAlgorithmInfo(PGPPublicKey key) {
return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength());
}
@@ -385,6 +479,30 @@ public class PgpHelper {
return convertFingerprintToHex(key.getFingerprint());
}
+ public static boolean isSecretKeyPrivateEmpty(PGPSecretKey secretKey) {
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
+ PGPPrivateKey testKey = secretKey.extractPrivateKey(
+ keyDecryptor);
+ if (testKey != null) {
+ return false;
+ }
+ } catch (PGPException e) { //exception if wrong key => not empty
+ return false; //all good if this fails, we likely didn't use the right password
+ }
+ return true;
+ }
+
+ public static boolean isSecretKeyPrivateEmpty(Context context, long keyId) {
+ PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
+ if (secretKey == null) {
+ Log.e(Constants.TAG, "Key could not be found!");
+ return false; //could be a public key, assume it is not empty
+ }
+ return isSecretKeyPrivateEmpty(secretKey);
+ }
+
public static String getSmallFingerPrint(long keyId) {
String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
while (fingerPrint.length() < 8) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
index 26842e4dc..142dfec01 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
@@ -84,6 +84,7 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import org.sufficientlysecure.keychain.util.Primes;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
+import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.R;
import android.content.Context;
@@ -308,6 +309,31 @@ public class PgpMain {
return secKeyRing;
}
+ public static void changeSecretKeyPassphrase(Context context,
+ PGPSecretKeyRing keyRing, String oldPassPhrase, String newPassPhrase,
+ ProgressDialogUpdater progress) throws IOException, PGPException, PGPException,
+ NoSuchProviderException {
+
+ updateProgress(progress, R.string.progress_buildingKey, 0, 100);
+ if (oldPassPhrase == null) {
+ oldPassPhrase = "";
+ }
+ if (newPassPhrase == null) {
+ newPassPhrase = "";
+ }
+
+ PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(keyRing,
+ oldPassPhrase.toCharArray(), newPassPhrase.toCharArray(), keyRing.getSecretKey().getKeyEncryptionAlgorithm(),
+ new SecureRandom(), BOUNCY_CASTLE_PROVIDER_NAME);
+
+ updateProgress(progress, R.string.progress_savingKeyRing, 50, 100);
+
+ ProviderHelper.saveKeyRing(context, newKeyRing);
+
+ updateProgress(progress, R.string.progress_done, 100, 100);
+
+ }
+
public static void buildSecretKey(Context context, ArrayList<String> userIds,
ArrayList<PGPSecretKey> keys, ArrayList<Integer> keysUsages, long masterKeyId,
String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
@@ -483,25 +509,22 @@ public class PgpMain {
* @param keyring
* @return
*/
+ @SuppressWarnings("unchecked")
public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
try {
if (keyring instanceof PGPSecretKeyRing) {
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
boolean save = true;
- try {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
- PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
- keyDecryptor);
- if (testKey == null) {
- // this is bad, something is very wrong... likely a --export-secret-subkeys
- // export
- save = false;
- status = Id.return_value.bad;
+
+ for (PGPSecretKey testSecretKey : new IterableIterator<PGPSecretKey>(secretKeyRing.getSecretKeys())) {
+ if (!testSecretKey.isMasterKey()) {
+ if (PgpHelper.isSecretKeyPrivateEmpty(testSecretKey)) {
+ // this is bad, something is very wrong...
+ save = false;
+ status = Id.return_value.bad;
+ }
}
- } catch (PGPException e) {
- // all good if this fails, we likely didn't use the right password
}
if (save) {
@@ -1109,7 +1132,7 @@ public class PgpMain {
} else {
PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context, pubKeyId);
- PGPSecretKey signingKey = PgpHelper.getSigningKey(context, masterKeyId);
+ PGPSecretKey signingKey = PgpHelper.getCertificationKey(context, masterKeyId);
if (signingKey == null) {
throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 3d4dddea5..b284eccaa 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -36,6 +36,7 @@ public class KeychainContract {
String IS_MASTER_KEY = "is_master_key";
String ALGORITHM = "algorithm";
String KEY_SIZE = "key_size";
+ String CAN_CERTIFY = "can_certify";
String CAN_SIGN = "can_sign";
String CAN_ENCRYPT = "can_encrypt";
String IS_REVOKED = "is_revoked";
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 4a2aeeb80..ef95ce7f7 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -31,7 +31,7 @@ import android.provider.BaseColumns;
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "apg.db";
- private static final int DATABASE_VERSION = 3;
+ private static final int DATABASE_VERSION = 4;
public interface Tables {
String KEY_RINGS = "key_rings";
@@ -48,6 +48,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KeysColumns.KEY_ID
+ " INT64, " + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY
+ " INTEGER, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE
+ + " INTEGER, " + KeysColumns.CAN_CERTIFY
+ " INTEGER, " + KeysColumns.CAN_SIGN + " INTEGER, " + KeysColumns.CAN_ENCRYPT
+ " INTEGER, " + KeysColumns.IS_REVOKED + " INTEGER, " + KeysColumns.CREATION
+ " INTEGER, " + KeysColumns.EXPIRY + " INTEGER, " + KeysColumns.KEY_DATA + " BLOB,"
@@ -93,6 +94,10 @@ public class KeychainDatabase extends SQLiteOpenHelper {
Log.w(Constants.TAG, "Upgrading database to version " + version);
switch (version) {
+ case 3:
+ db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY + " INTEGER DEFAULT 0;");
+ db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;");
+ break;
default:
break;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index 23f9616e0..c63d9e772 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -367,6 +367,7 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(KeysColumns.IS_MASTER_KEY, KeysColumns.IS_MASTER_KEY);
projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
+ projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY);
projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN);
projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 36049a64c..2665456ea 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.helper.PgpMain;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -370,11 +371,20 @@ public class ProviderHelper {
private static ContentProviderOperation buildSecretKeyOperations(Context context,
long keyRingRowId, PGPSecretKey key, int rank) throws IOException {
ContentValues values = new ContentValues();
+
+ boolean has_private = true;
+ if (key.isMasterKey()) {
+ if (PgpHelper.isSecretKeyPrivateEmpty(key)) {
+ has_private = false;
+ }
+ }
+
values.put(Keys.KEY_ID, key.getKeyID());
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm());
values.put(Keys.KEY_SIZE, key.getPublicKey().getBitStrength());
- values.put(Keys.CAN_SIGN, PgpHelper.isSigningKey(key));
+ values.put(Keys.CAN_CERTIFY, (PgpHelper.isCertificationKey(key) && has_private));
+ values.put(Keys.CAN_SIGN, (PgpHelper.isSigningKey(key) && has_private));
values.put(Keys.CAN_ENCRYPT, PgpHelper.isEncryptionKey(key));
values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked());
values.put(Keys.CREATION, PgpHelper.getCreationDate(key).getTime() / 1000);
@@ -486,6 +496,49 @@ public class ProviderHelper {
}
/**
+ * Get empty status of master key of keyring by its row id
+ *
+ * @param context
+ * @param keyRingRowId
+ * @return
+ */
+ public static boolean getSecretMasterKeyCanSign(Context context, long keyRingRowId) {
+ Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId));
+ return getMasterKeyCanSign(context, queryUri, keyRingRowId);
+ }
+
+ /**
+ * Private helper method to get master key private empty status of keyring by its row id
+ *
+ * @param context
+ * @param queryUri
+ * @param keyRingRowId
+ * @return
+ */
+ private static boolean getMasterKeyCanSign(Context context, Uri queryUri, long keyRingRowId) {
+ String[] projection = new String[] { KeyRings.MASTER_KEY_ID, "(SELECT COUNT(sign_keys." +
+ Keys._ID + ") FROM " + Tables.KEYS + " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
+ + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND sign_keys."
+ + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY + " = 1) AS sign", };
+
+ ContentResolver cr = context.getContentResolver();
+ Cursor cursor = cr.query(queryUri, projection, null, null, null);
+
+ long masterKeyId = -1;
+ if (cursor != null && cursor.moveToFirst()) {
+ int masterKeyIdCol = cursor.getColumnIndex("sign");
+
+ masterKeyId = cursor.getLong(masterKeyIdCol);
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return (masterKeyId > 0);
+ }
+
+ /**
* Get master key id of keyring by its row id
*
* @param context
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index e525fe96e..48afdff5c 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -123,6 +123,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String SAVE_KEYRING_KEYS = "keys";
public static final String SAVE_KEYRING_KEYS_USAGES = "keysUsages";
public static final String SAVE_KEYRING_MASTER_KEY_ID = "masterKeyId";
+ public static final String SAVE_KEYRING_CAN_SIGN = "can_sign";
// generate key
public static final String GENERATE_KEY_ALGORITHM = "algorithm";
@@ -523,6 +524,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Input */
String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
String newPassPhrase = data.getString(SAVE_KEYRING_NEW_PASSPHRASE);
+ boolean canSign = true;
+
+ if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) {
+ canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN);
+ }
+
if (newPassPhrase == null) {
newPassPhrase = oldPassPhrase;
}
@@ -533,8 +540,13 @@ public class KeychainIntentService extends IntentService implements ProgressDial
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
/* Operation */
- PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
+ if (!canSign) { //library fails, fix later
+ //PgpMain.changeSecretKeyPassphrase(this, ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
+ //oldPassPhrase, newPassPhrase, this);
+ } else {
+ PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
newPassPhrase, this);
+ }
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
/* Output */
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index 87b1204a4..ed81c2aa8 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -62,6 +62,7 @@ import android.widget.ViewFlipper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.regex.Matcher;
@@ -642,7 +643,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
}
try {
- inStream = new FileInputStream(mInputFilename);
+ inStream = new BufferedInputStream(new FileInputStream(mInputFilename));
} catch (FileNotFoundException e) {
Log.e(Constants.TAG, "File not found!", e);
Toast.makeText(this, getString(R.string.error_fileNotFound, e.getMessage()),
@@ -659,6 +660,9 @@ public class DecryptActivity extends SherlockFragmentActivity {
// get decryption key for this inStream
try {
try {
+ if (inStream.markSupported()) {
+ inStream.mark(200); //should probably set this to the max size of two pgpF objects, if it even needs to be anything other than 0.
+ }
mSecretKeyId = PgpMain.getDecryptionKeyId(this, inStream);
if (mSecretKeyId == Id.key.none) {
throw new PgpMain.PgpGeneralException(
@@ -666,6 +670,9 @@ public class DecryptActivity extends SherlockFragmentActivity {
}
mAssumeSymmetricEncryption = false;
} catch (PgpMain.NoAsymmetricEncryptionException e) {
+ if (inStream.markSupported()) {
+ inStream.reset();
+ }
mSecretKeyId = Id.key.symmetric;
if (!PgpMain.hasSymmetricEncryption(this, inStream)) {
throw new PgpMain.PgpGeneralException(
@@ -914,7 +921,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
case Id.request.output_filename: {
if (resultCode == RESULT_OK && data != null) {
try {
- String path = data.getData().getPath();
+ String path = FileHelper.getPath(this, data.getData());
Log.d(Constants.TAG, "path=" + path);
mFileDialog.setFilename(path);
@@ -944,3 +951,4 @@ public class DecryptActivity extends SherlockFragmentActivity {
}
}
+
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 90ee9838e..3d819a824 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -75,6 +75,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
+ public static final String EXTRA_MASTER_CAN_SIGN = "masterCanSign";
// results when saving key
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
@@ -97,6 +98,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
Vector<String> mUserIds;
Vector<PGPSecretKey> mKeys;
Vector<Integer> mKeysUsages;
+ boolean masterCanSign = true;
// will be set to false to build layout later in handler
private boolean mBuildLayout = true;
@@ -192,6 +194,13 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
});
+ //disable key passhphrase changing with empty private keys for no
+ //library fails, fix later
+ if (!masterCanSign) {
+ mChangePassPhrase.setEnabled(false);
+ mNoPassphrase.setEnabled(false);
+ }
+
if (mBuildLayout) {
buildLayout();
}
@@ -317,6 +326,9 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
if (extras != null) {
+ if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
+ masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
+ }
if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
@@ -394,10 +406,12 @@ public class EditKeyActivity extends SherlockFragmentActivity {
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mUserIdsView.setType(Id.type.user_id);
+ mUserIdsView.setCanEdit(masterCanSign);
mUserIdsView.setUserIds(mUserIds);
container.addView(mUserIdsView);
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mKeysView.setType(Id.type.key);
+ mKeysView.setCanEdit(masterCanSign);
mKeysView.setKeys(mKeys, mKeysUsages);
container.addView(mKeysView);
@@ -447,6 +461,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
data.putIntegerArrayList(KeychainIntentService.SAVE_KEYRING_KEYS_USAGES,
getKeysUsages(mKeysView));
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
+ data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, masterCanSign);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 9d73fc6e5..c6b2d196a 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -678,6 +678,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
long encryptionKeyIds[] = null;
int compressionId = 0;
boolean signOnly = false;
+ long mSecretKeyIdToPass = 0;
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
@@ -685,9 +686,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
if (passPhrase.length() == 0) {
passPhrase = null;
}
-
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase);
} else {
+ mSecretKeyIdToPass = mSecretKeyId;
encryptionKeyIds = mEncryptionKeyIds;
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
}
@@ -733,7 +734,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
useAsciiArmor = mAsciiArmorDemand;
}
- data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyId);
+ data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyIdToPass);
data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_AMOR, useAsciiArmor);
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
index 0e6cdd6a1..52ce19f97 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
@@ -70,18 +70,19 @@ public class KeyListSecretActivity extends KeyListActivity {
}
}
- public void checkPassPhraseAndEdit(long masterKeyId) {
+ public void checkPassPhraseAndEdit(long masterKeyId, boolean masterCanSign) {
String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
if (passPhrase == null) {
- showPassphraseDialog(masterKeyId);
+ showPassphraseDialog(masterKeyId, masterCanSign);
} else {
PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId);
+ editKey(masterKeyId, masterCanSign);
}
}
- private void showPassphraseDialog(final long masterKeyId) {
+ private void showPassphraseDialog(final long masterKeyId, boolean masterCanSign) {
// Message is received after passphrase is cached
+ final boolean mCanSign = masterCanSign;
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
@@ -89,7 +90,7 @@ public class KeyListSecretActivity extends KeyListActivity {
String passPhrase = PassphraseCacheService.getCachedPassphrase(
KeyListSecretActivity.this, masterKeyId);
PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId);
+ editKey(masterKeyId, mCanSign);
}
}
};
@@ -115,9 +116,10 @@ public class KeyListSecretActivity extends KeyListActivity {
startActivityForResult(intent, 0);
}
- private void editKey(long masterKeyId) {
+ private void editKey(long masterKeyId, boolean masterCanSign) {
Intent intent = new Intent(EditKeyActivity.ACTION_EDIT_KEY);
intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
+ intent.putExtra(EditKeyActivity.EXTRA_MASTER_CAN_SIGN, masterCanSign);
startActivityForResult(intent, 0);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
index f4ba2b4d9..e41755840 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
@@ -91,9 +91,11 @@ public class KeyListSecretFragment extends KeyListFragment implements
long masterKeyId = ProviderHelper
.getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
+ boolean masterCanSign = ProviderHelper.getSecretMasterKeyCanSign(mKeyListSecretActivity, keyRingRowId);
+
switch (item.getItemId()) {
case Id.menu.edit:
- mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId);
+ mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId, masterCanSign);
return true;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
index 14ccb17c7..10acd38d9 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
@@ -34,8 +34,11 @@ public class SelectSecretKeyActivity extends SherlockFragmentActivity {
public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX
+ "SELECT_SECRET_KEYRING";
+ public static final String EXTRA_FILTER_CERTIFY = "filter_certify";
+
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
public static final String RESULT_EXTRA_USER_ID = "userId";
+ public static boolean filterCertify = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -61,6 +64,8 @@ public class SelectSecretKeyActivity extends SherlockFragmentActivity {
// }
// });
+ filterCertify = getIntent().getBooleanExtra(EXTRA_FILTER_CERTIFY, false);
+
handleIntent(getIntent());
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
index a3d9167a3..4871b74bc 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java
@@ -91,12 +91,21 @@ public class SelectSecretKeyFragment extends SherlockListFragment implements
// sample only has one Loader, so we don't care about the ID.
Uri baseUri = KeyRings.buildSecretKeyRingsUri();
+ String CapFilter = null;
+ if (((SelectSecretKeyActivity)getActivity()).filterCertify == true) {
+ CapFilter = "(cert>0)";
+ }
+
// These are the rows that we will retrieve.
long now = new Date().getTime() / 1000;
String[] projection = new String[] {
KeyRings._ID,
KeyRings.MASTER_KEY_ID,
UserIds.USER_ID,
+ "(SELECT COUNT(cert_keys." + Keys._ID + ") FROM " + Tables.KEYS
+ + " AS cert_keys WHERE cert_keys." + Keys.KEY_RING_ROW_ID + " = "
+ + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND cert_keys."
+ + Keys.CAN_CERTIFY + " = '1') AS cert",
"(SELECT COUNT(available_keys." + Keys._ID + ") FROM " + Tables.KEYS
+ " AS available_keys WHERE available_keys." + Keys.KEY_RING_ROW_ID + " = "
+ KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
@@ -127,7 +136,7 @@ public class SelectSecretKeyFragment extends SherlockListFragment implements
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, projection, null, null, orderBy);
+ return new CursorLoader(getActivity(), baseUri, projection, CapFilter, null, orderBy);
}
@Override
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
index 21d55aca0..1e7fe0120 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
@@ -121,6 +121,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
// kick off the SecretKey selection activity so the user chooses which key to sign with
// first
Intent intent = new Intent(this, SelectSecretKeyActivity.class);
+ intent.putExtra(SelectSecretKeyActivity.EXTRA_FILTER_CERTIFY, true);
startActivityForResult(intent, Id.request.secret_keys);
}
}
@@ -295,7 +296,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
switch (requestCode) {
case Id.request.secret_keys: {
if (resultCode == RESULT_OK) {
- mMasterKeyId = data.getLongExtra(EXTRA_KEY_ID, 0);
+ Bundle bundle = data.getExtras();
+ mMasterKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID);
// re-enable the sign button so the user can initiate the sign process
Button sign = (Button) findViewById(R.id.sign);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
index 2f9cdb3b1..7c4d9cea3 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
@@ -191,4 +191,5 @@ public class FileDialogFragment extends DialogFragment {
Log.w(Constants.TAG, "Messenger is null!", e);
}
}
-} \ No newline at end of file
+}
+
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
index 504de9d69..10fc74551 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.dialog;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
@@ -63,6 +64,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
private Messenger mMessenger;
private EditText mPassphraseEditText;
+ private boolean canKB;
/**
* Creates new instance of this dialog fragment
@@ -137,8 +139,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity();
-
- long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
+ final long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
@@ -152,8 +153,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
} else {
// TODO: by master key id???
- secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
- activity, secretKeyId));
+ secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId));
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
if (secretKey == null) {
@@ -165,6 +165,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
}
});
alert.setCancelable(false);
+ canKB = false;
return alert.create();
}
String userId = PgpHelper.getMainUserIdSafe(activity, secretKey);
@@ -184,24 +185,43 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
@Override
public void onClick(DialogInterface dialog, int id) {
dismiss();
-
+ long curKeyIndex = 1;
+ boolean keyOK = true;
String passPhrase = mPassphraseEditText.getText().toString();
long keyId;
- if (secretKey != null) {
- try {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
- passPhrase.toCharArray());
- PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
- if (testKey == null) {
+ PGPSecretKey clickSecretKey = secretKey;
+
+ if (clickSecretKey != null) {
+ while (keyOK == true) {
+ if (clickSecretKey != null) { //check again for loop
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ passPhrase.toCharArray());
+ PGPPrivateKey testKey = clickSecretKey.extractPrivateKey(keyDecryptor);
+ if (testKey == null) {
+ if (!clickSecretKey.isMasterKey()) {
+ Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
+ Toast.LENGTH_SHORT).show();
+ return;
+ } else {
+ clickSecretKey = PgpHelper.getKeyNum(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId), curKeyIndex);
+ curKeyIndex++; //does post-increment work like C?
+ continue;
+ }
+ } else {
+ keyOK = false;
+ }
+ } catch (PGPException e) {
+ Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
+ .show();
+ return;
+ }
+ } else {
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show();
- return;
+ return; //ran out of keys to try
}
- } catch (PGPException e) {
- Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
- .show();
- return;
}
keyId = secretKey.getKeyID();
} else {
@@ -211,6 +231,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
// cache the new passphrase
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
+ if (keyOK == false && clickSecretKey.getKeyID() != keyId) {
+ PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), passPhrase);
+ }
sendMessageToHandler(MESSAGE_OKAY);
}
@@ -224,18 +247,20 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
}
});
+ canKB = true;
return alert.create();
}
@Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
-
+ if (canKB) {
// request focus and open soft keyboard
- mPassphraseEditText.requestFocus();
- getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ mPassphraseEditText.requestFocus();
+ getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
- mPassphraseEditText.setOnEditorActionListener(this);
+ mPassphraseEditText.setOnEditorActionListener(this);
+ }
}
/**
@@ -272,4 +297,5 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
}
}
-} \ No newline at end of file
+}
+
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
index 1122fc522..e9a5674cd 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
@@ -125,6 +125,14 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
super.onFinishInflate();
}
+ public void setCanEdit(boolean bCanEdit) {
+ if (!bCanEdit) {
+ mDeleteButton.setVisibility(View.INVISIBLE);
+ mUsage.setEnabled(false);
+ mExpiryDateButton.setEnabled(false);
+ }
+ }
+
public void setValue(PGPSecretKey key, boolean isMasterKey, int usage) {
mKey = key;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
index 8e8d33886..75c764540 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
@@ -151,6 +151,13 @@ public class KeyListAdapter extends CursorTreeAdapter {
masterKeyIcon.setVisibility(View.VISIBLE);
}
+ ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
+ if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
+ certifyIcon.setVisibility(View.GONE);
+ } else {
+ certifyIcon.setVisibility(View.VISIBLE);
+ }
+
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
encryptIcon.setVisibility(View.GONE);
@@ -160,7 +167,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
- signIcon.setVisibility(View.GONE);
+ signIcon.setVisibility(View.GONE);
} else {
signIcon.setVisibility(View.VISIBLE);
}
@@ -212,7 +219,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
switch (type) {
case CHILD_FINGERPRINT:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
- Keys.KEY_SIZE, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
+ Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
// use only master key for fingerprint
@@ -227,7 +234,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
case CHILD_KEY:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
- Keys.KEY_SIZE, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
+ Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
if (mKeyType == Id.type.public_key) {
@@ -261,4 +268,4 @@ public class KeyListAdapter extends CursorTreeAdapter {
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
}
-} \ No newline at end of file
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
index 7142e4426..898b05372 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
@@ -45,6 +45,7 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
@@ -55,12 +56,14 @@ import java.util.Vector;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
private LayoutInflater mInflater;
private View mAdd;
+ private ImageView mPlusButton;
private ViewGroup mEditors;
private TextView mTitle;
private int mType = 0;
private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize;
+ private boolean canEdit = true;
private SherlockFragmentActivity mActivity;
@@ -99,6 +102,14 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
}
+ public void setCanEdit(boolean bCanEdit) {
+ canEdit = bCanEdit;
+ mPlusButton = (ImageView)findViewById(R.id.plusbutton);
+ if (!canEdit) {
+ mPlusButton.setVisibility(View.INVISIBLE);
+ }
+ }
+
/** {@inheritDoc} */
@Override
protected void onFinishInflate() {
@@ -129,6 +140,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
/** {@inheritDoc} */
public void onClick(View v) {
+ if (canEdit) {
switch (mType) {
case Id.type.user_id: {
UserIdEditor view = (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
@@ -205,6 +217,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
}
this.updateEditorsVisible();
+ }
}
public void setUserIds(Vector<String> list) {
@@ -221,6 +234,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
+ view.setCanEdit(canEdit);
mEditors.addView(view);
}
@@ -241,6 +255,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(list.get(i), isMasterKey, usages.get(i));
+ view.setCanEdit(canEdit);
mEditors.addView(view);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
index da8ac94ee..17423136f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
@@ -139,4 +139,4 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
return mInflater.inflate(R.layout.select_key_item, null);
}
-} \ No newline at end of file
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
index 2215d29e7..5b43ebbd9 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
@@ -56,6 +56,16 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
}
}
+ public void setCanEdit(boolean bCanEdit) {
+ if (!bCanEdit) {
+ mDeleteButton.setVisibility(View.INVISIBLE);
+ mName.setEnabled(false);
+ mIsMainUserId.setEnabled(false);
+ mEmail.setEnabled(false);
+ mComment.setEnabled(false);
+ }
+ }
+
public static class NoEmailException extends Exception {
static final long serialVersionUID = 0xf812773344L;