mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-19 20:31:52 -05:00
Merge with ashh87s pull request
This commit is contained in:
commit
30fa184e7e
BIN
OpenPGP-Keychain/res/drawable-hdpi/certify_small.png
Normal file
BIN
OpenPGP-Keychain/res/drawable-hdpi/certify_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
OpenPGP-Keychain/res/drawable-mdpi/certify_small.png
Normal file
BIN
OpenPGP-Keychain/res/drawable-mdpi/certify_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
OpenPGP-Keychain/res/drawable/certify_small.png
Normal file
BIN
OpenPGP-Keychain/res/drawable/certify_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -41,6 +41,7 @@
|
|||||||
android:text="Section Name" />
|
android:text="Section Name" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:id="@+id/plusbutton"
|
||||||
style="@style/PlusButton"
|
style="@style/PlusButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -54,4 +55,4 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="6dip" />
|
android:paddingBottom="6dip" />
|
||||||
|
|
||||||
</org.sufficientlysecure.keychain.ui.widget.SectionView>
|
</org.sufficientlysecure.keychain.ui.widget.SectionView>
|
||||||
|
@ -63,6 +63,12 @@
|
|||||||
android:paddingBottom="2dip"
|
android:paddingBottom="2dip"
|
||||||
android:paddingTop="2dip" >
|
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
|
<ImageView
|
||||||
android:id="@+id/ic_encryptKey"
|
android:id="@+id/ic_encryptKey"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -93,4 +99,4 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
limitations under the License.
|
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"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -49,4 +49,4 @@
|
|||||||
android:layout_height="1dip"
|
android:layout_height="1dip"
|
||||||
android:background="?android:attr/listDivider"/>
|
android:background="?android:attr/listDivider"/>
|
||||||
|
|
||||||
</org.thialfihar.android.apg.ui.widget.KeyServerEditor>
|
</org.sufficientlysecure.keychain.ui.widget.KeyServerEditor>
|
||||||
|
@ -24,12 +24,16 @@ import java.util.Locale;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
|
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
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.Constants;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
@ -76,6 +80,22 @@ public class PgpHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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")
|
@SuppressWarnings("unchecked")
|
||||||
public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
|
public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
|
||||||
Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
|
Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
|
||||||
@ -102,6 +122,19 @@ public class PgpHelper {
|
|||||||
return signingKeys;
|
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) {
|
public static Vector<PGPPublicKey> getUsableEncryptKeys(PGPPublicKeyRing keyRing) {
|
||||||
Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>();
|
Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>();
|
||||||
Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing);
|
Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing);
|
||||||
@ -137,6 +170,24 @@ public class PgpHelper {
|
|||||||
return isExpired(key.getPublicKey());
|
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) {
|
public static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) {
|
||||||
Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
|
Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
|
||||||
Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
|
Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
|
||||||
@ -188,6 +239,19 @@ public class PgpHelper {
|
|||||||
return encryptKeys.get(0);
|
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) {
|
public static PGPSecretKey getSigningKey(Context context, long masterKeyId) {
|
||||||
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
|
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
|
||||||
masterKeyId);
|
masterKeyId);
|
||||||
@ -313,6 +377,36 @@ public class PgpHelper {
|
|||||||
return isSigningKey(key.getPublicKey());
|
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) {
|
public static String getAlgorithmInfo(PGPPublicKey key) {
|
||||||
return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength());
|
return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength());
|
||||||
}
|
}
|
||||||
@ -385,6 +479,30 @@ public class PgpHelper {
|
|||||||
return convertFingerprintToHex(key.getFingerprint());
|
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) {
|
public static String getSmallFingerPrint(long keyId) {
|
||||||
String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
|
String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
|
||||||
while (fingerPrint.length() < 8) {
|
while (fingerPrint.length() < 8) {
|
||||||
|
@ -84,6 +84,7 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
|||||||
import org.sufficientlysecure.keychain.util.Primes;
|
import org.sufficientlysecure.keychain.util.Primes;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
||||||
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -308,6 +309,31 @@ public class PgpMain {
|
|||||||
return secKeyRing;
|
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,
|
public static void buildSecretKey(Context context, ArrayList<String> userIds,
|
||||||
ArrayList<PGPSecretKey> keys, ArrayList<Integer> keysUsages, long masterKeyId,
|
ArrayList<PGPSecretKey> keys, ArrayList<Integer> keysUsages, long masterKeyId,
|
||||||
String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
|
String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
|
||||||
@ -483,25 +509,22 @@ public class PgpMain {
|
|||||||
* @param keyring
|
* @param keyring
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
|
public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
|
||||||
int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
|
int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
|
||||||
try {
|
try {
|
||||||
if (keyring instanceof PGPSecretKeyRing) {
|
if (keyring instanceof PGPSecretKeyRing) {
|
||||||
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
|
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
|
||||||
boolean save = true;
|
boolean save = true;
|
||||||
try {
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
for (PGPSecretKey testSecretKey : new IterableIterator<PGPSecretKey>(secretKeyRing.getSecretKeys())) {
|
||||||
.setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
|
if (!testSecretKey.isMasterKey()) {
|
||||||
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
|
if (PgpHelper.isSecretKeyPrivateEmpty(testSecretKey)) {
|
||||||
keyDecryptor);
|
// this is bad, something is very wrong...
|
||||||
if (testKey == null) {
|
save = false;
|
||||||
// this is bad, something is very wrong... likely a --export-secret-subkeys
|
status = Id.return_value.bad;
|
||||||
// export
|
}
|
||||||
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) {
|
if (save) {
|
||||||
@ -1109,7 +1132,7 @@ public class PgpMain {
|
|||||||
} else {
|
} else {
|
||||||
PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context, pubKeyId);
|
PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context, pubKeyId);
|
||||||
|
|
||||||
PGPSecretKey signingKey = PgpHelper.getSigningKey(context, masterKeyId);
|
PGPSecretKey signingKey = PgpHelper.getCertificationKey(context, masterKeyId);
|
||||||
if (signingKey == null) {
|
if (signingKey == null) {
|
||||||
throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
|
throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ public class KeychainContract {
|
|||||||
String IS_MASTER_KEY = "is_master_key";
|
String IS_MASTER_KEY = "is_master_key";
|
||||||
String ALGORITHM = "algorithm";
|
String ALGORITHM = "algorithm";
|
||||||
String KEY_SIZE = "key_size";
|
String KEY_SIZE = "key_size";
|
||||||
|
String CAN_CERTIFY = "can_certify";
|
||||||
String CAN_SIGN = "can_sign";
|
String CAN_SIGN = "can_sign";
|
||||||
String CAN_ENCRYPT = "can_encrypt";
|
String CAN_ENCRYPT = "can_encrypt";
|
||||||
String IS_REVOKED = "is_revoked";
|
String IS_REVOKED = "is_revoked";
|
||||||
|
@ -31,7 +31,7 @@ import android.provider.BaseColumns;
|
|||||||
|
|
||||||
public class KeychainDatabase extends SQLiteOpenHelper {
|
public class KeychainDatabase extends SQLiteOpenHelper {
|
||||||
private static final String DATABASE_NAME = "apg.db";
|
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 {
|
public interface Tables {
|
||||||
String KEY_RINGS = "key_rings";
|
String KEY_RINGS = "key_rings";
|
||||||
@ -48,6 +48,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
|||||||
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KeysColumns.KEY_ID
|
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KeysColumns.KEY_ID
|
||||||
+ " INT64, " + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY
|
+ " INT64, " + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY
|
||||||
+ " INTEGER, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE
|
+ " INTEGER, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE
|
||||||
|
+ " INTEGER, " + KeysColumns.CAN_CERTIFY
|
||||||
+ " INTEGER, " + KeysColumns.CAN_SIGN + " INTEGER, " + KeysColumns.CAN_ENCRYPT
|
+ " INTEGER, " + KeysColumns.CAN_SIGN + " INTEGER, " + KeysColumns.CAN_ENCRYPT
|
||||||
+ " INTEGER, " + KeysColumns.IS_REVOKED + " INTEGER, " + KeysColumns.CREATION
|
+ " INTEGER, " + KeysColumns.IS_REVOKED + " INTEGER, " + KeysColumns.CREATION
|
||||||
+ " INTEGER, " + KeysColumns.EXPIRY + " INTEGER, " + KeysColumns.KEY_DATA + " BLOB,"
|
+ " 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);
|
Log.w(Constants.TAG, "Upgrading database to version " + version);
|
||||||
|
|
||||||
switch (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:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -367,6 +367,7 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
projectionMap.put(KeysColumns.IS_MASTER_KEY, KeysColumns.IS_MASTER_KEY);
|
projectionMap.put(KeysColumns.IS_MASTER_KEY, KeysColumns.IS_MASTER_KEY);
|
||||||
projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
|
projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
|
||||||
projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
|
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_SIGN, KeysColumns.CAN_SIGN);
|
||||||
projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
|
projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
|
||||||
projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
|
projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
|
||||||
|
@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.helper.PgpMain;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
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.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
@ -370,11 +371,20 @@ public class ProviderHelper {
|
|||||||
private static ContentProviderOperation buildSecretKeyOperations(Context context,
|
private static ContentProviderOperation buildSecretKeyOperations(Context context,
|
||||||
long keyRingRowId, PGPSecretKey key, int rank) throws IOException {
|
long keyRingRowId, PGPSecretKey key, int rank) throws IOException {
|
||||||
ContentValues values = new ContentValues();
|
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.KEY_ID, key.getKeyID());
|
||||||
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
|
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
|
||||||
values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm());
|
values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm());
|
||||||
values.put(Keys.KEY_SIZE, key.getPublicKey().getBitStrength());
|
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.CAN_ENCRYPT, PgpHelper.isEncryptionKey(key));
|
||||||
values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked());
|
values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked());
|
||||||
values.put(Keys.CREATION, PgpHelper.getCreationDate(key).getTime() / 1000);
|
values.put(Keys.CREATION, PgpHelper.getCreationDate(key).getTime() / 1000);
|
||||||
@ -485,6 +495,49 @@ public class ProviderHelper {
|
|||||||
return getMasterKeyId(context, queryUri, keyRingRowId);
|
return getMasterKeyId(context, queryUri, keyRingRowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Get master key id of keyring by its row id
|
||||||
*
|
*
|
||||||
|
@ -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 = "keys";
|
||||||
public static final String SAVE_KEYRING_KEYS_USAGES = "keysUsages";
|
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_MASTER_KEY_ID = "masterKeyId";
|
||||||
|
public static final String SAVE_KEYRING_CAN_SIGN = "can_sign";
|
||||||
|
|
||||||
// generate key
|
// generate key
|
||||||
public static final String GENERATE_KEY_ALGORITHM = "algorithm";
|
public static final String GENERATE_KEY_ALGORITHM = "algorithm";
|
||||||
@ -523,6 +524,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
/* Input */
|
/* Input */
|
||||||
String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
|
String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
|
||||||
String newPassPhrase = data.getString(SAVE_KEYRING_NEW_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) {
|
if (newPassPhrase == null) {
|
||||||
newPassPhrase = oldPassPhrase;
|
newPassPhrase = oldPassPhrase;
|
||||||
}
|
}
|
||||||
@ -533,8 +540,13 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
|||||||
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
|
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
|
||||||
|
|
||||||
/* Operation */
|
/* 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);
|
newPassPhrase, this);
|
||||||
|
}
|
||||||
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
|
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
|
@ -62,6 +62,7 @@ import android.widget.ViewFlipper;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -642,7 +643,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inStream = new FileInputStream(mInputFilename);
|
inStream = new BufferedInputStream(new FileInputStream(mInputFilename));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.e(Constants.TAG, "File not found!", e);
|
Log.e(Constants.TAG, "File not found!", e);
|
||||||
Toast.makeText(this, getString(R.string.error_fileNotFound, e.getMessage()),
|
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
|
// get decryption key for this inStream
|
||||||
try {
|
try {
|
||||||
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);
|
mSecretKeyId = PgpMain.getDecryptionKeyId(this, inStream);
|
||||||
if (mSecretKeyId == Id.key.none) {
|
if (mSecretKeyId == Id.key.none) {
|
||||||
throw new PgpMain.PgpGeneralException(
|
throw new PgpMain.PgpGeneralException(
|
||||||
@ -666,6 +670,9 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
}
|
}
|
||||||
mAssumeSymmetricEncryption = false;
|
mAssumeSymmetricEncryption = false;
|
||||||
} catch (PgpMain.NoAsymmetricEncryptionException e) {
|
} catch (PgpMain.NoAsymmetricEncryptionException e) {
|
||||||
|
if (inStream.markSupported()) {
|
||||||
|
inStream.reset();
|
||||||
|
}
|
||||||
mSecretKeyId = Id.key.symmetric;
|
mSecretKeyId = Id.key.symmetric;
|
||||||
if (!PgpMain.hasSymmetricEncryption(this, inStream)) {
|
if (!PgpMain.hasSymmetricEncryption(this, inStream)) {
|
||||||
throw new PgpMain.PgpGeneralException(
|
throw new PgpMain.PgpGeneralException(
|
||||||
@ -914,7 +921,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
case Id.request.output_filename: {
|
case Id.request.output_filename: {
|
||||||
if (resultCode == RESULT_OK && data != null) {
|
if (resultCode == RESULT_OK && data != null) {
|
||||||
try {
|
try {
|
||||||
String path = data.getData().getPath();
|
String path = FileHelper.getPath(this, data.getData());
|
||||||
Log.d(Constants.TAG, "path=" + path);
|
Log.d(Constants.TAG, "path=" + path);
|
||||||
|
|
||||||
mFileDialog.setFilename(path);
|
mFileDialog.setFilename(path);
|
||||||
@ -944,3 +951,4 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
|||||||
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
|
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
|
||||||
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
|
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
|
||||||
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
|
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
|
||||||
|
public static final String EXTRA_MASTER_CAN_SIGN = "masterCanSign";
|
||||||
|
|
||||||
// results when saving key
|
// results when saving key
|
||||||
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
|
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
|
||||||
@ -97,6 +98,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
|||||||
Vector<String> mUserIds;
|
Vector<String> mUserIds;
|
||||||
Vector<PGPSecretKey> mKeys;
|
Vector<PGPSecretKey> mKeys;
|
||||||
Vector<Integer> mKeysUsages;
|
Vector<Integer> mKeysUsages;
|
||||||
|
boolean masterCanSign = true;
|
||||||
|
|
||||||
// will be set to false to build layout later in handler
|
// will be set to false to build layout later in handler
|
||||||
private boolean mBuildLayout = true;
|
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) {
|
if (mBuildLayout) {
|
||||||
buildLayout();
|
buildLayout();
|
||||||
}
|
}
|
||||||
@ -317,6 +326,9 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (extras != null) {
|
if (extras != null) {
|
||||||
|
if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
|
||||||
|
masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
|
||||||
|
}
|
||||||
if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
|
if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
|
||||||
long masterKeyId = extras.getLong(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);
|
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
|
||||||
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||||
mUserIdsView.setType(Id.type.user_id);
|
mUserIdsView.setType(Id.type.user_id);
|
||||||
|
mUserIdsView.setCanEdit(masterCanSign);
|
||||||
mUserIdsView.setUserIds(mUserIds);
|
mUserIdsView.setUserIds(mUserIds);
|
||||||
container.addView(mUserIdsView);
|
container.addView(mUserIdsView);
|
||||||
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
||||||
mKeysView.setType(Id.type.key);
|
mKeysView.setType(Id.type.key);
|
||||||
|
mKeysView.setCanEdit(masterCanSign);
|
||||||
mKeysView.setKeys(mKeys, mKeysUsages);
|
mKeysView.setKeys(mKeys, mKeysUsages);
|
||||||
container.addView(mKeysView);
|
container.addView(mKeysView);
|
||||||
|
|
||||||
@ -447,6 +461,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
|||||||
data.putIntegerArrayList(KeychainIntentService.SAVE_KEYRING_KEYS_USAGES,
|
data.putIntegerArrayList(KeychainIntentService.SAVE_KEYRING_KEYS_USAGES,
|
||||||
getKeysUsages(mKeysView));
|
getKeysUsages(mKeysView));
|
||||||
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
|
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
|
||||||
|
data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, masterCanSign);
|
||||||
|
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
|
|
||||||
|
@ -678,6 +678,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
|
|||||||
long encryptionKeyIds[] = null;
|
long encryptionKeyIds[] = null;
|
||||||
int compressionId = 0;
|
int compressionId = 0;
|
||||||
boolean signOnly = false;
|
boolean signOnly = false;
|
||||||
|
long mSecretKeyIdToPass = 0;
|
||||||
|
|
||||||
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
|
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
|
||||||
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
||||||
@ -685,9 +686,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
|
|||||||
if (passPhrase.length() == 0) {
|
if (passPhrase.length() == 0) {
|
||||||
passPhrase = null;
|
passPhrase = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase);
|
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase);
|
||||||
} else {
|
} else {
|
||||||
|
mSecretKeyIdToPass = mSecretKeyId;
|
||||||
encryptionKeyIds = mEncryptionKeyIds;
|
encryptionKeyIds = mEncryptionKeyIds;
|
||||||
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
|
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
|
||||||
}
|
}
|
||||||
@ -733,7 +734,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
|
|||||||
useAsciiArmor = mAsciiArmorDemand;
|
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.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_AMOR, useAsciiArmor);
|
||||||
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
|
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, encryptionKeyIds);
|
||||||
data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
|
data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId);
|
||||||
|
@ -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);
|
String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
|
||||||
if (passPhrase == null) {
|
if (passPhrase == null) {
|
||||||
showPassphraseDialog(masterKeyId);
|
showPassphraseDialog(masterKeyId, masterCanSign);
|
||||||
} else {
|
} else {
|
||||||
PgpMain.setEditPassPhrase(passPhrase);
|
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
|
// Message is received after passphrase is cached
|
||||||
|
final boolean mCanSign = masterCanSign;
|
||||||
Handler returnHandler = new Handler() {
|
Handler returnHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
@ -89,7 +90,7 @@ public class KeyListSecretActivity extends KeyListActivity {
|
|||||||
String passPhrase = PassphraseCacheService.getCachedPassphrase(
|
String passPhrase = PassphraseCacheService.getCachedPassphrase(
|
||||||
KeyListSecretActivity.this, masterKeyId);
|
KeyListSecretActivity.this, masterKeyId);
|
||||||
PgpMain.setEditPassPhrase(passPhrase);
|
PgpMain.setEditPassPhrase(passPhrase);
|
||||||
editKey(masterKeyId);
|
editKey(masterKeyId, mCanSign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -115,9 +116,10 @@ public class KeyListSecretActivity extends KeyListActivity {
|
|||||||
startActivityForResult(intent, 0);
|
startActivityForResult(intent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void editKey(long masterKeyId) {
|
private void editKey(long masterKeyId, boolean masterCanSign) {
|
||||||
Intent intent = new Intent(EditKeyActivity.ACTION_EDIT_KEY);
|
Intent intent = new Intent(EditKeyActivity.ACTION_EDIT_KEY);
|
||||||
intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
|
||||||
|
intent.putExtra(EditKeyActivity.EXTRA_MASTER_CAN_SIGN, masterCanSign);
|
||||||
startActivityForResult(intent, 0);
|
startActivityForResult(intent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,9 +91,11 @@ public class KeyListSecretFragment extends KeyListFragment implements
|
|||||||
long masterKeyId = ProviderHelper
|
long masterKeyId = ProviderHelper
|
||||||
.getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
|
.getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
|
||||||
|
|
||||||
|
boolean masterCanSign = ProviderHelper.getSecretMasterKeyCanSign(mKeyListSecretActivity, keyRingRowId);
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case Id.menu.edit:
|
case Id.menu.edit:
|
||||||
mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId);
|
mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId, masterCanSign);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -34,8 +34,11 @@ public class SelectSecretKeyActivity extends SherlockFragmentActivity {
|
|||||||
public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX
|
public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX
|
||||||
+ "SELECT_SECRET_KEYRING";
|
+ "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_MASTER_KEY_ID = "masterKeyId";
|
||||||
public static final String RESULT_EXTRA_USER_ID = "userId";
|
public static final String RESULT_EXTRA_USER_ID = "userId";
|
||||||
|
public static boolean filterCertify = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -61,6 +64,8 @@ public class SelectSecretKeyActivity extends SherlockFragmentActivity {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
filterCertify = getIntent().getBooleanExtra(EXTRA_FILTER_CERTIFY, false);
|
||||||
|
|
||||||
handleIntent(getIntent());
|
handleIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,12 +91,21 @@ public class SelectSecretKeyFragment extends SherlockListFragment implements
|
|||||||
// sample only has one Loader, so we don't care about the ID.
|
// sample only has one Loader, so we don't care about the ID.
|
||||||
Uri baseUri = KeyRings.buildSecretKeyRingsUri();
|
Uri baseUri = KeyRings.buildSecretKeyRingsUri();
|
||||||
|
|
||||||
|
String CapFilter = null;
|
||||||
|
if (((SelectSecretKeyActivity)getActivity()).filterCertify == true) {
|
||||||
|
CapFilter = "(cert>0)";
|
||||||
|
}
|
||||||
|
|
||||||
// These are the rows that we will retrieve.
|
// These are the rows that we will retrieve.
|
||||||
long now = new Date().getTime() / 1000;
|
long now = new Date().getTime() / 1000;
|
||||||
String[] projection = new String[] {
|
String[] projection = new String[] {
|
||||||
KeyRings._ID,
|
KeyRings._ID,
|
||||||
KeyRings.MASTER_KEY_ID,
|
KeyRings.MASTER_KEY_ID,
|
||||||
UserIds.USER_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
|
"(SELECT COUNT(available_keys." + Keys._ID + ") FROM " + Tables.KEYS
|
||||||
+ " AS available_keys WHERE available_keys." + Keys.KEY_RING_ROW_ID + " = "
|
+ " AS available_keys WHERE available_keys." + Keys.KEY_RING_ROW_ID + " = "
|
||||||
+ KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._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
|
// Now create and return a CursorLoader that will take care of
|
||||||
// creating a Cursor for the data being displayed.
|
// 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
|
@Override
|
||||||
|
@ -121,6 +121,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
|
|||||||
// kick off the SecretKey selection activity so the user chooses which key to sign with
|
// kick off the SecretKey selection activity so the user chooses which key to sign with
|
||||||
// first
|
// first
|
||||||
Intent intent = new Intent(this, SelectSecretKeyActivity.class);
|
Intent intent = new Intent(this, SelectSecretKeyActivity.class);
|
||||||
|
intent.putExtra(SelectSecretKeyActivity.EXTRA_FILTER_CERTIFY, true);
|
||||||
startActivityForResult(intent, Id.request.secret_keys);
|
startActivityForResult(intent, Id.request.secret_keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,7 +296,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case Id.request.secret_keys: {
|
case Id.request.secret_keys: {
|
||||||
if (resultCode == RESULT_OK) {
|
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
|
// re-enable the sign button so the user can initiate the sign process
|
||||||
Button sign = (Button) findViewById(R.id.sign);
|
Button sign = (Button) findViewById(R.id.sign);
|
||||||
|
@ -191,4 +191,5 @@ public class FileDialogFragment extends DialogFragment {
|
|||||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.dialog;
|
|||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
@ -63,6 +64,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
|
|
||||||
private Messenger mMessenger;
|
private Messenger mMessenger;
|
||||||
private EditText mPassphraseEditText;
|
private EditText mPassphraseEditText;
|
||||||
|
private boolean canKB;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this dialog fragment
|
* Creates new instance of this dialog fragment
|
||||||
@ -137,8 +139,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
|
final long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
|
||||||
long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
|
|
||||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||||
|
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
||||||
@ -152,8 +153,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
|
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
|
||||||
} else {
|
} else {
|
||||||
// TODO: by master key id???
|
// TODO: by master key id???
|
||||||
secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
|
secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId));
|
||||||
activity, secretKeyId));
|
|
||||||
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
||||||
|
|
||||||
if (secretKey == null) {
|
if (secretKey == null) {
|
||||||
@ -165,6 +165,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
alert.setCancelable(false);
|
alert.setCancelable(false);
|
||||||
|
canKB = false;
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
String userId = PgpHelper.getMainUserIdSafe(activity, secretKey);
|
String userId = PgpHelper.getMainUserIdSafe(activity, secretKey);
|
||||||
@ -184,24 +185,43 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
|
long curKeyIndex = 1;
|
||||||
|
boolean keyOK = true;
|
||||||
String passPhrase = mPassphraseEditText.getText().toString();
|
String passPhrase = mPassphraseEditText.getText().toString();
|
||||||
long keyId;
|
long keyId;
|
||||||
if (secretKey != null) {
|
PGPSecretKey clickSecretKey = secretKey;
|
||||||
try {
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
if (clickSecretKey != null) {
|
||||||
.setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
while (keyOK == true) {
|
||||||
passPhrase.toCharArray());
|
if (clickSecretKey != null) { //check again for loop
|
||||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
|
try {
|
||||||
if (testKey == null) {
|
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.makeText(activity, R.string.error_couldNotExtractPrivateKey,
|
||||||
Toast.LENGTH_SHORT).show();
|
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();
|
keyId = secretKey.getKeyID();
|
||||||
} else {
|
} else {
|
||||||
@ -211,6 +231,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
// cache the new passphrase
|
// cache the new passphrase
|
||||||
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
||||||
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
|
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
|
||||||
|
if (keyOK == false && clickSecretKey.getKeyID() != keyId) {
|
||||||
|
PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), passPhrase);
|
||||||
|
}
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_OKAY);
|
sendMessageToHandler(MESSAGE_OKAY);
|
||||||
}
|
}
|
||||||
@ -224,18 +247,20 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
canKB = true;
|
||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle arg0) {
|
public void onActivityCreated(Bundle arg0) {
|
||||||
super.onActivityCreated(arg0);
|
super.onActivityCreated(arg0);
|
||||||
|
if (canKB) {
|
||||||
// request focus and open soft keyboard
|
// request focus and open soft keyboard
|
||||||
mPassphraseEditText.requestFocus();
|
mPassphraseEditText.requestFocus();
|
||||||
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +125,14 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
|
|||||||
super.onFinishInflate();
|
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) {
|
public void setValue(PGPSecretKey key, boolean isMasterKey, int usage) {
|
||||||
mKey = key;
|
mKey = key;
|
||||||
|
|
||||||
|
@ -151,6 +151,13 @@ public class KeyListAdapter extends CursorTreeAdapter {
|
|||||||
masterKeyIcon.setVisibility(View.VISIBLE);
|
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);
|
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
|
||||||
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
|
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
|
||||||
encryptIcon.setVisibility(View.GONE);
|
encryptIcon.setVisibility(View.GONE);
|
||||||
@ -160,7 +167,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
|
|||||||
|
|
||||||
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
|
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
|
||||||
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
|
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
|
||||||
signIcon.setVisibility(View.GONE);
|
signIcon.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
signIcon.setVisibility(View.VISIBLE);
|
signIcon.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
@ -212,7 +219,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case CHILD_FINGERPRINT:
|
case CHILD_FINGERPRINT:
|
||||||
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
|
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";
|
sortOrder = Keys.RANK + " ASC";
|
||||||
|
|
||||||
// use only master key for fingerprint
|
// use only master key for fingerprint
|
||||||
@ -227,7 +234,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
|
|||||||
|
|
||||||
case CHILD_KEY:
|
case CHILD_KEY:
|
||||||
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
|
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";
|
sortOrder = Keys.RANK + " ASC";
|
||||||
|
|
||||||
if (mKeyType == Id.type.public_key) {
|
if (mKeyType == Id.type.public_key) {
|
||||||
@ -261,4 +268,4 @@ public class KeyListAdapter extends CursorTreeAdapter {
|
|||||||
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
|
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -55,12 +56,14 @@ import java.util.Vector;
|
|||||||
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
|
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
private View mAdd;
|
private View mAdd;
|
||||||
|
private ImageView mPlusButton;
|
||||||
private ViewGroup mEditors;
|
private ViewGroup mEditors;
|
||||||
private TextView mTitle;
|
private TextView mTitle;
|
||||||
private int mType = 0;
|
private int mType = 0;
|
||||||
|
|
||||||
private Choice mNewKeyAlgorithmChoice;
|
private Choice mNewKeyAlgorithmChoice;
|
||||||
private int mNewKeySize;
|
private int mNewKeySize;
|
||||||
|
private boolean canEdit = true;
|
||||||
|
|
||||||
private SherlockFragmentActivity mActivity;
|
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} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
@ -129,6 +140,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
if (canEdit) {
|
||||||
switch (mType) {
|
switch (mType) {
|
||||||
case Id.type.user_id: {
|
case Id.type.user_id: {
|
||||||
UserIdEditor view = (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
|
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();
|
this.updateEditorsVisible();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserIds(Vector<String> list) {
|
public void setUserIds(Vector<String> list) {
|
||||||
@ -221,6 +234,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
if (mEditors.getChildCount() == 0) {
|
if (mEditors.getChildCount() == 0) {
|
||||||
view.setIsMainUserId(true);
|
view.setIsMainUserId(true);
|
||||||
}
|
}
|
||||||
|
view.setCanEdit(canEdit);
|
||||||
mEditors.addView(view);
|
mEditors.addView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +255,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
view.setEditorListener(this);
|
view.setEditorListener(this);
|
||||||
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
||||||
view.setValue(list.get(i), isMasterKey, usages.get(i));
|
view.setValue(list.get(i), isMasterKey, usages.get(i));
|
||||||
|
view.setCanEdit(canEdit);
|
||||||
mEditors.addView(view);
|
mEditors.addView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,4 +139,4 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
|
|||||||
return mInflater.inflate(R.layout.select_key_item, null);
|
return mInflater.inflate(R.layout.select_key_item, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
public static class NoEmailException extends Exception {
|
||||||
static final long serialVersionUID = 0xf812773344L;
|
static final long serialVersionUID = 0xf812773344L;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user