aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-04-11 14:39:35 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2014-04-11 14:39:35 +0200
commit85bb3d9480ccc52908e7a43379c5e2eda9dbd7f1 (patch)
tree4a20a9065d9411d35b720a0fd446ab4e2ff89b9f /OpenKeychain/src
parent0687f7f40e1aecf4fbc109c3ab3fa2c3613546b3 (diff)
parentbaa3c86e1246d486d80c963ddc6c64b58f2a5093 (diff)
downloadopen-keychain-85bb3d9480ccc52908e7a43379c5e2eda9dbd7f1.tar.gz
open-keychain-85bb3d9480ccc52908e7a43379c5e2eda9dbd7f1.tar.bz2
open-keychain-85bb3d9480ccc52908e7a43379c5e2eda9dbd7f1.zip
Merge pull request #553 from Valodim/split-masterKeyId
Split master key & partial fix for uid order
Diffstat (limited to 'OpenKeychain/src')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java135
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java47
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java52
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java61
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java1
-rw-r--r--OpenKeychain/src/main/res/layout-large/import_keys_activity.xml21
-rw-r--r--OpenKeychain/src/main/res/layout/import_keys_activity.xml53
-rw-r--r--OpenKeychain/src/main/res/layout/import_keys_content.xml50
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml2
15 files changed, 244 insertions, 244 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
index c42446c9e..c0aaf6d89 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java
@@ -51,7 +51,7 @@ public class ExportHelper {
public void deleteKey(Uri dataUri, Handler deleteHandler) {
try {
- long masterKeyId = ProviderHelper.getMasterKeyId(mActivity, dataUri);
+ long masterKeyId = ProviderHelper.extractOrGetMasterKeyId(mActivity, dataUri);
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(deleteHandler);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 3e0520c2a..8e1bb3f60 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -122,15 +122,20 @@ public class ProviderHelper {
* Find the master key id related to a given query. The id will either be extracted from the
* query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
*/
- public static long getMasterKeyId(Context context, Uri queryUri) throws NotFoundException {
+ public static long extractOrGetMasterKeyId(Context context, Uri queryUri)
+ throws NotFoundException {
// try extracting from the uri first
-// String firstSegment = queryUri.getPathSegments().get(1);
-// if(!firstSegment.equals("find")) try {
-// return Long.parseLong(firstSegment);
-// } catch(NumberFormatException e) {
-// // didn't work? oh well.
-// Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying...");
-// }
+ String firstSegment = queryUri.getPathSegments().get(1);
+ if(!firstSegment.equals("find")) try {
+ return Long.parseLong(firstSegment);
+ } catch(NumberFormatException e) {
+ // didn't work? oh well.
+ Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying...");
+ }
+ return getMasterKeyId(context, queryUri);
+ }
+
+ public static long getMasterKeyId(Context context, Uri queryUri) throws NotFoundException {
Object data = getGenericData(context, queryUri, KeyRings.MASTER_KEY_ID, FIELD_TYPE_INTEGER);
if(data != null) {
return (Long) data;
@@ -461,70 +466,49 @@ public class ProviderHelper {
return ContentProviderOperation.newInsert(uri).withValues(values).build();
}
- public static ArrayList<String> getKeyRingsAsArmoredString(Context context, long[] masterKeyIds) {
- ArrayList<String> output = new ArrayList<String>();
-
- if (masterKeyIds != null && masterKeyIds.length > 0) {
-
- Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, masterKeyIds);
-
- if (cursor != null) {
- int masterIdCol = cursor.getColumnIndex(KeyRingData.MASTER_KEY_ID);
- int dataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
- if (cursor.moveToFirst()) {
- do {
- Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
+ private static String getKeyRingAsArmoredString(Context context, byte[] data) throws IOException {
+ Object keyRing = null;
+ if (data != null) {
+ keyRing = PgpConversionHelper.BytesToPGPKeyRing(data);
+ }
- // get actual keyring data blob and write it to ByteArrayOutputStream
- try {
- Object keyRing = null;
- byte[] data = cursor.getBlob(dataCol);
- if (data != null) {
- keyRing = PgpConversionHelper.BytesToPGPKeyRing(data);
- }
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ArmoredOutputStream aos = new ArmoredOutputStream(bos);
+ aos.setHeader("Version", PgpHelper.getFullVersion(context));
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ArmoredOutputStream aos = new ArmoredOutputStream(bos);
- aos.setHeader("Version", PgpHelper.getFullVersion(context));
+ if (keyRing instanceof PGPSecretKeyRing) {
+ aos.write(((PGPSecretKeyRing) keyRing).getEncoded());
+ } else if (keyRing instanceof PGPPublicKeyRing) {
+ aos.write(((PGPPublicKeyRing) keyRing).getEncoded());
+ }
+ aos.close();
- if (keyRing instanceof PGPSecretKeyRing) {
- aos.write(((PGPSecretKeyRing) keyRing).getEncoded());
- } else if (keyRing instanceof PGPPublicKeyRing) {
- aos.write(((PGPPublicKeyRing) keyRing).getEncoded());
- }
- aos.close();
+ String armoredKey = bos.toString("UTF-8");
- String armoredKey = bos.toString("UTF-8");
+ Log.d(Constants.TAG, "armoredKey:" + armoredKey);
- Log.d(Constants.TAG, "armoredKey:" + armoredKey);
+ return armoredKey;
+ }
- output.add(armoredKey);
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException", e);
- }
- } while (cursor.moveToNext());
- }
- }
+ public static String getKeyRingAsArmoredString(Context context, Uri uri)
+ throws NotFoundException, IOException {
+ byte[] data = (byte[]) ProviderHelper.getGenericData(
+ context, uri, KeyRingData.KEY_RING_DATA, ProviderHelper.FIELD_TYPE_BLOB);
+ return getKeyRingAsArmoredString(context, data);
+ }
- if (cursor != null) {
- cursor.close();
- }
+ // TODO This method is NOT ACTUALLY USED. Is this preparation for something, or just dead code?
+ public static ArrayList<String> getKeyRingsAsArmoredString(Context context, long[] masterKeyIds)
+ throws IOException {
+ ArrayList<String> output = new ArrayList<String>();
- } else {
+ if (masterKeyIds == null || masterKeyIds.length == 0) {
Log.e(Constants.TAG, "No master keys given!");
- }
-
- if (output.size() > 0) {
return output;
- } else {
- return null;
}
- }
-
- private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, long[] masterKeyIds) {
- Cursor cursor = null;
- if (masterKeyIds != null && masterKeyIds.length > 0) {
+ // Build a cursor for the selected masterKeyIds
+ Cursor cursor = null; {
String inMasterKeyList = KeyRingData.MASTER_KEY_ID + " IN (";
for (int i = 0; i < masterKeyIds.length; ++i) {
if (i != 0) {
@@ -536,10 +520,37 @@ public class ProviderHelper {
cursor = context.getContentResolver().query(KeyRingData.buildPublicKeyRingUri(), new String[] {
KeyRingData._ID, KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA
- }, inMasterKeyList, null, null);
+ }, inMasterKeyList, null, null);
}
- return cursor;
+ if (cursor != null) {
+ int masterIdCol = cursor.getColumnIndex(KeyRingData.MASTER_KEY_ID);
+ int dataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
+ if (cursor.moveToFirst()) {
+ do {
+ Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
+
+ byte[] data = cursor.getBlob(dataCol);
+
+ // get actual keyring data blob and write it to ByteArrayOutputStream
+ try {
+ output.add(getKeyRingAsArmoredString(context, data));
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException", e);
+ }
+ } while (cursor.moveToNext());
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ if (output.size() > 0) {
+ return output;
+ } else {
+ return null;
+ }
}
public static ArrayList<String> getRegisteredApiApps(Context context) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
index 321d2a83f..a13c7a953 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
@@ -180,7 +180,8 @@ public class AccountSettingsFragment extends Fragment implements
if (resultCode == Activity.RESULT_OK) {
// select newly created key
try {
- long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), data.getData());
+ long masterKeyId = ProviderHelper.extractOrGetMasterKeyId(
+ getActivity(), data.getData());
mSelectKeyFragment.selectKey(masterKeyId);
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index cbc71ce6a..91d9b5584 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -200,6 +200,31 @@ public class PassphraseCacheService extends Service {
return cachedPassphrase;
}
+ public static boolean hasPassphrase(PGPSecretKeyRing secretKeyRing) {
+ PGPSecretKey secretKey = null;
+ boolean foundValidKey = false;
+ for (Iterator keys = secretKeyRing.getSecretKeys(); keys.hasNext(); ) {
+ secretKey = (PGPSecretKey) keys.next();
+ if (!secretKey.isPrivateKeyEmpty()) {
+ foundValidKey = true;
+ break;
+ }
+ }
+ if(!foundValidKey) {
+ return false;
+ }
+
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider("SC").build("".toCharArray());
+ PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
+ return testKey == null;
+ } catch(PGPException e) {
+ // this means the crc check failed -> passphrase required
+ return true;
+ }
+ }
+
/**
* Checks if key has a passphrase.
*
@@ -210,27 +235,7 @@ public class PassphraseCacheService extends Service {
// check if the key has no passphrase
try {
PGPSecretKeyRing secRing = ProviderHelper.getPGPSecretKeyRing(context, secretKeyId);
- PGPSecretKey secretKey = null;
- boolean foundValidKey = false;
- for (Iterator keys = secRing.getSecretKeys(); keys.hasNext(); ) {
- secretKey = (PGPSecretKey) keys.next();
- if (!secretKey.isPrivateKeyEmpty()) {
- foundValidKey = true;
- break;
- }
- }
-
- if (!foundValidKey) {
- return false;
- }
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- "SC").build("".toCharArray());
- PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
- if (testKey != null) {
- return false;
- }
- } catch (PGPException e) {
- // silently catch
+ return hasPassphrase(secRing);
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 84f0c41cf..696f79cd7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -39,10 +39,12 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
+import android.widget.Toast;
import com.beardedhen.androidbootstrap.BootstrapButton;
import com.devspark.appmsg.AppMsg;
+import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
@@ -287,34 +289,16 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
Log.d(Constants.TAG, "uri: " + mDataUri);
try {
- // get master key id using row id
- long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
- finallyEdit(masterKeyId);
- } catch (ProviderHelper.NotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- private void finallyEdit(final long masterKeyId) {
- if (masterKeyId != 0) {
- PGPSecretKey masterKey = null;
- try {
- mKeyRing = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId);
+ Uri secretUri = KeychainContract.KeyRingData.buildSecretKeyRingUri(mDataUri);
+ mKeyRing = (PGPSecretKeyRing) ProviderHelper.getPGPKeyRing(this, secretUri);
- masterKey = mKeyRing.getSecretKey();
+ PGPSecretKey masterKey = mKeyRing.getSecretKey();
mMasterCanSign = PgpKeyHelper.isCertificationKey(mKeyRing.getSecretKey());
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(mKeyRing.getSecretKeys())) {
mKeys.add(key);
mKeysUsages.add(-1); // get usage when view is created
}
- } catch (ProviderHelper.NotFoundException e) {
- Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId);
- AppMsg.makeText(this, R.string.error_no_secret_key_found, AppMsg.STYLE_ALERT).show();
- // TODO
- }
- if (masterKey != null) {
+
boolean isSet = false;
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
Log.d(Constants.TAG, "Added userId " + userId);
@@ -327,17 +311,23 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
}
mUserIds.add(userId);
}
- }
- }
- mCurrentPassphrase = "";
- buildLayout(false);
+ buildLayout(false);
+
+ mCurrentPassphrase = "";
+ mIsPassphraseSet = PassphraseCacheService.hasPassphrase(mKeyRing);
+ if (!mIsPassphraseSet) {
+ // check "no passphrase" checkbox and remove button
+ mNoPassphrase.setChecked(true);
+ mChangePassphrase.setVisibility(View.GONE);
+ }
+
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e);
+ Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show();
+ finish();
+ }
- mIsPassphraseSet = PassphraseCacheService.hasPassphrase(this, masterKeyId);
- if (!mIsPassphraseSet) {
- // check "no passphrase" checkbox and remove button
- mNoPassphrase.setChecked(true);
- mChangePassphrase.setVisibility(View.GONE);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
index 2ec4dd89e..a99c9eca8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
@@ -165,10 +165,11 @@ public class EncryptAsymmetricFragment extends Fragment {
if (preselectedEncryptionKeyIds != null) {
Vector<Long> goodIds = new Vector<Long>();
for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
- // TODO check for available encrypt keys... is this even relevant?
+ // TODO One query per selected key?! wtf
try {
long id = ProviderHelper.getMasterKeyId(getActivity(),
- KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(preselectedEncryptionKeyIds[i]))
+ KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
+ Long.toString(preselectedEncryptionKeyIds[i]))
);
goodIds.add(id);
} catch (ProviderHelper.NotFoundException e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index dceb9a0fc..ca26cac1c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -219,12 +219,8 @@ public class ViewKeyActivity extends ActionBarActivity {
} else {
// get public keyring as ascii armored string
try {
- long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
-
- ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
- this, new long[]{masterKeyId});
-
- content = keyringArmored.get(0);
+ Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
+ content = ProviderHelper.getKeyRingAsArmoredString(this, uri);
// Android will fail with android.os.TransactionTooLargeException if key is too big
// see http://www.lonestarprod.com/?p=34
@@ -233,8 +229,12 @@ public class ViewKeyActivity extends ActionBarActivity {
AppMsg.STYLE_ALERT).show();
return;
}
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "error processing key!", e);
+ AppMsg.makeText(this, R.string.error_invalid_data, AppMsg.STYLE_ALERT).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
+ AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
}
}
@@ -259,16 +259,18 @@ public class ViewKeyActivity extends ActionBarActivity {
private void copyToClipboard(Uri dataUri) {
// get public keyring as ascii armored string
try {
- long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
-
- ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
- this, new long[]{masterKeyId});
+ Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
+ String keyringArmored = ProviderHelper.getKeyRingAsArmoredString(this, uri);
- ClipboardReflection.copyToClipboard(this, keyringArmored.get(0));
+ ClipboardReflection.copyToClipboard(this, keyringArmored);
AppMsg.makeText(this, R.string.key_copied_to_clipboard, AppMsg.STYLE_INFO)
.show();
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "error processing key!", e);
+ AppMsg.makeText(this, R.string.error_key_processing, AppMsg.STYLE_ALERT).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
+ AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
index a7543d194..386342a48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
@@ -331,11 +331,8 @@ public class ViewKeyMainFragment extends Fragment implements
}
private void encryptToContact(Uri dataUri) {
- // TODO preselect from uri? should be feasible without trivial query
try {
- long keyId = ProviderHelper.getMasterKeyId(getActivity(),
- KeyRingData.buildPublicKeyRingUri(dataUri));
-
+ long keyId = ProviderHelper.extractOrGetMasterKeyId(getActivity(), dataUri);
long[] encryptionKeyIds = new long[]{ keyId };
Intent intent = new Intent(getActivity(), EncryptActivity.class);
intent.setAction(EncryptActivity.ACTION_ENCRYPT);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
index 5631d40ea..44bde963e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
@@ -21,9 +21,12 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
+import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.IterableIterator;
@@ -46,31 +49,19 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
public int bitStrength;
public String algorithm;
public boolean secretKey;
+ public String mPrimaryUserId;
private boolean mSelected;
private byte[] mBytes = new byte[]{};
- public ImportKeysListEntry(ImportKeysListEntry b) {
- this.userIds = b.userIds;
- this.keyId = b.keyId;
- this.revoked = b.revoked;
- this.date = b.date;
- this.fingerPrintHex = b.fingerPrintHex;
- this.keyIdHex = b.keyIdHex;
- this.bitStrength = b.bitStrength;
- this.algorithm = b.algorithm;
- this.secretKey = b.secretKey;
- this.mSelected = b.mSelected;
- this.mBytes = b.mBytes;
- }
-
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mPrimaryUserId);
dest.writeStringList(userIds);
dest.writeLong(keyId);
dest.writeByte((byte) (revoked ? 1 : 0));
@@ -88,6 +79,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() {
public ImportKeysListEntry createFromParcel(final Parcel source) {
ImportKeysListEntry vr = new ImportKeysListEntry();
+ vr.mPrimaryUserId = source.readString();
vr.userIds = new ArrayList<String>();
source.readStringList(vr.userIds);
vr.keyId = source.readLong();
@@ -198,6 +190,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
this.userIds = userIds;
}
+ public String getPrimaryUserId() {
+ return mPrimaryUserId;
+ }
+
+ public void setPrimaryUserId(String uid) {
+ mPrimaryUserId = uid;
+ }
+
/**
* Constructor for later querying from keyserver
*/
@@ -229,20 +229,39 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
} else {
secretKey = false;
}
+ PGPPublicKey key = pgpKeyRing.getPublicKey();
userIds = new ArrayList<String>();
- for (String userId : new IterableIterator<String>(pgpKeyRing.getPublicKey().getUserIDs())) {
+ for (String userId : new IterableIterator<String>(key.getUserIDs())) {
userIds.add(userId);
+ for(PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignaturesForID(userId))) {
+ if(sig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.PRIMARY_USER_ID)) {
+ try {
+ // make sure it's actually valid
+ sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME), key);
+ if (sig.verifyCertification(userId, key)) {
+ mPrimaryUserId = userId;
+ }
+ } catch(Exception e) {
+ // nothing bad happens, the key is just not considered the primary key id
+ }
+ }
+
+ }
+ }
+ // if there was no user id flagged as primary, use the first one
+ if(mPrimaryUserId == null) {
+ mPrimaryUserId = userIds.get(0);
}
- this.keyId = pgpKeyRing.getPublicKey().getKeyID();
+ this.keyId = key.getKeyID();
this.keyIdHex = PgpKeyHelper.convertKeyIdToHex(keyId);
- this.revoked = pgpKeyRing.getPublicKey().isRevoked();
- this.fingerPrintHex = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey()
- .getFingerprint());
- this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength();
- final int algorithm = pgpKeyRing.getPublicKey().getAlgorithm();
+ this.revoked = key.isRevoked();
+ this.fingerPrintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint());
+ this.bitStrength = key.getBitStrength();
+ final int algorithm = key.getAlgorithm();
this.algorithm = getAlgorithmFromId(algorithm);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
index d2d21093e..7e9a3d800 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
@@ -28,14 +28,19 @@ import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+
+import com.devspark.appmsg.AppMsg;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
+import java.io.IOException;
import java.util.ArrayList;
public class ShareQrCodeDialogFragment extends DialogFragment {
@@ -77,7 +82,6 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
mFingerprintOnly = getArguments().getBoolean(ARG_FINGERPRINT_ONLY);
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
-
alert.setTitle(R.string.share_qr_code_dialog_title);
LayoutInflater inflater = activity.getLayoutInflater();
@@ -95,7 +99,8 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
getActivity(), KeyRings.buildUnifiedKeyRingUri(dataUri),
KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if(blob == null) {
- // TODO error handling?!
+ Log.e(Constants.TAG, "key not found!");
+ AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
return null;
}
@@ -106,20 +111,18 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
} else {
mText.setText(R.string.share_qr_code_dialog_start);
- // TODO works, but
- long masterKeyId = 0;
try {
- masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
+ Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
+ content = ProviderHelper.getKeyRingAsArmoredString(getActivity(), uri);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "error processing key!", e);
+ AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT).show();
+ return null;
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
+ AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
+ return null;
}
- // get public keyring as ascii armored string
- ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
- getActivity(), new long[] { masterKeyId });
-
- // TODO: binary?
-
- content = keyringArmored.get(0);
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs
// http://bit.ly/O5vfaR
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
index d1753de83..02149124c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
@@ -294,6 +294,7 @@ public class HkpKeyServer extends KeyServer {
userIds.add(tmp);
}
entry.setUserIds(userIds);
+ entry.setPrimaryUserId(userIds.get(0));
results.add(entry);
}
diff --git a/OpenKeychain/src/main/res/layout-large/import_keys_activity.xml b/OpenKeychain/src/main/res/layout-large/import_keys_activity.xml
deleted file mode 100644
index 2cb408441..000000000
--- a/OpenKeychain/src/main/res/layout-large/import_keys_activity.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <android.support.v4.widget.DrawerLayout
- xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
- android:id="@+id/drawer_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
-
- <include layout="@layout/drawer_list"/>
-
- </android.support.v4.widget.DrawerLayout>
-
- <include layout="@layout/import_keys_content"/>
-
-</FrameLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/import_keys_activity.xml b/OpenKeychain/src/main/res/layout/import_keys_activity.xml
index c82607a33..eb1333704 100644
--- a/OpenKeychain/src/main/res/layout/import_keys_activity.xml
+++ b/OpenKeychain/src/main/res/layout/import_keys_activity.xml
@@ -1,11 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/drawer_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/content_frame"
+ android:layout_marginLeft="@dimen/drawer_content_padding"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true">
- <include layout="@layout/import_keys_content"/>
+ <FrameLayout
+ android:id="@+id/import_navigation_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:orientation="vertical"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp" />
- <include layout="@layout/drawer_list" />
+ <LinearLayout
+ android:id="@+id/import_footer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp">
-</android.support.v4.widget.DrawerLayout> \ No newline at end of file
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/import_import"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:text="@string/import_import"
+ bootstrapbutton:bb_icon_left="fa-download"
+ bootstrapbutton:bb_type="info" />
+
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/import_keys_list_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_above="@+id/import_footer"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/import_navigation_fragment"
+ android:orientation="vertical"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp" />
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/import_keys_content.xml b/OpenKeychain/src/main/res/layout/import_keys_content.xml
deleted file mode 100644
index eb1333704..000000000
--- a/OpenKeychain/src/main/res/layout/import_keys_content.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
- android:id="@+id/content_frame"
- android:layout_marginLeft="@dimen/drawer_content_padding"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true">
-
- <FrameLayout
- android:id="@+id/import_navigation_fragment"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:orientation="vertical"
- android:paddingLeft="4dp"
- android:paddingRight="4dp" />
-
- <LinearLayout
- android:id="@+id/import_footer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:orientation="vertical"
- android:paddingLeft="16dp"
- android:paddingRight="16dp">
-
- <com.beardedhen.androidbootstrap.BootstrapButton
- android:id="@+id/import_import"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_marginTop="4dp"
- android:layout_marginBottom="4dp"
- android:text="@string/import_import"
- bootstrapbutton:bb_icon_left="fa-download"
- bootstrapbutton:bb_type="info" />
-
- </LinearLayout>
-
- <FrameLayout
- android:id="@+id/import_keys_list_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_above="@+id/import_footer"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/import_navigation_fragment"
- android:orientation="vertical"
- android:paddingLeft="4dp"
- android:paddingRight="4dp" />
-</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index c21a120a2..a58e3a484 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -525,5 +525,7 @@
<string name="label_cert_type">Type</string>
<string name="can_certify">can certify</string>
<string name="can_certify_not">cannot certify</string>
+ <string name="error_key_not_found">Key not found!</string>
+ <string name="error_key_processing">Error processing key!</string>
</resources>