When exporting secret keyrings, also export public part

This commit is contained in:
Dominik Schürmann 2013-01-08 17:48:56 +01:00
parent 68039d3a8a
commit 6fd44a0ec5
7 changed files with 73 additions and 84 deletions

View File

@ -345,8 +345,8 @@
<string name="help_about_version">Version:</string> <string name="help_about_version">Version:</string>
<!-- Import from QR Code --> <!-- Import from QR Code -->
<string name="import_from_qr_code_import">Import keyring (only locally)</string> <string name="import_from_qr_code_import">Import keyring(s) (only locally)</string>
<string name="import_from_qr_code_import_sign_and_upload">Import, Sign, and upload keyring</string> <string name="import_from_qr_code_import_sign_and_upload">Import, Sign, and upload keyring(s)</string>
<string name="import_from_qr_code_finish">Finish</string> <string name="import_from_qr_code_finish">Finish</string>
<!-- Intent labels --> <!-- Intent labels -->

View File

@ -74,7 +74,6 @@ import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactory
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
import org.thialfihar.android.apg.provider.ProviderHelper; import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.service.ApgIntentService; import org.thialfihar.android.apg.service.ApgIntentService;
import org.thialfihar.android.apg.ui.dialog.SetPassphraseDialogFragment;
import org.thialfihar.android.apg.util.HkpKeyServer; import org.thialfihar.android.apg.util.HkpKeyServer;
import org.thialfihar.android.apg.util.InputData; import org.thialfihar.android.apg.util.InputData;
import org.thialfihar.android.apg.util.PositionAwareInputStream; import org.thialfihar.android.apg.util.PositionAwareInputStream;
@ -607,12 +606,12 @@ public class PGPMain {
return returnData; return returnData;
} }
public static Bundle exportKeyRings(Context context, ArrayList<Long> keyRingRowIds, public static Bundle exportKeyRings(Context context, ArrayList<Long> keyRingMasterKeyIds,
OutputStream outStream, ProgressDialogUpdater progress) throws ApgGeneralException, int keyType, OutputStream outStream, ProgressDialogUpdater progress)
FileNotFoundException, PGPException, IOException { throws ApgGeneralException, FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
if (keyRingRowIds.size() == 1) { if (keyRingMasterKeyIds.size() == 1) {
updateProgress(progress, R.string.progress_exportingKey, 0, 100); updateProgress(progress, R.string.progress_exportingKey, 0, 100);
} else { } else {
updateProgress(progress, R.string.progress_exportingKeys, 0, 100); updateProgress(progress, R.string.progress_exportingKeys, 0, 100);
@ -621,66 +620,49 @@ public class PGPMain {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady)); throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady));
} }
ArmoredOutputStream out = new ArmoredOutputStream(outStream);
out.setHeader("Version", getFullVersion(context)); // export public keyrings...
ArmoredOutputStream outPub = new ArmoredOutputStream(outStream);
outPub.setHeader("Version", getFullVersion(context));
int numKeys = 0; int numKeys = 0;
for (int i = 0; i < keyRingRowIds.size(); ++i) { for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
updateProgress(progress, i * 100 / keyRingRowIds.size(), 100); // double the needed time if exporting both public and secret parts
if (keyType == Id.type.secret_key) {
// try to get it as a PGPPublicKeyRing, if that fails try to get it as a SecretKeyRing updateProgress(progress, i * 100 / keyRingMasterKeyIds.size() / 2, 100);
PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(context,
keyRingRowIds.get(i));
if (publicKeyRing != null) {
publicKeyRing.encode(out);
} else { } else {
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByRowId(context, updateProgress(progress, i * 100 / keyRingMasterKeyIds.size(), 100);
keyRingRowIds.get(i));
if (secretKeyRing != null) {
secretKeyRing.encode(out);
} else {
continue;
} }
PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(
context, keyRingMasterKeyIds.get(i));
if (publicKeyRing != null) {
publicKeyRing.encode(outPub);
} }
++numKeys; ++numKeys;
} }
out.close(); outPub.close();
returnData.putInt(ApgIntentService.RESULT_EXPORT, numKeys);
updateProgress(progress, R.string.progress_done, 100, 100); // if we export secret keyrings, append all secret parts after the public parts
if (keyType == Id.type.secret_key) {
ArmoredOutputStream outSec = new ArmoredOutputStream(outStream);
outSec.setHeader("Version", getFullVersion(context));
return returnData; for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
} updateProgress(progress, i * 100 / keyRingMasterKeyIds.size() / 2, 100);
public static Bundle getKeyRings(Context context, long[] masterKeyIds, OutputStream outStream, PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
ProgressDialogUpdater progress) throws ApgGeneralException, FileNotFoundException, context, keyRingMasterKeyIds.get(i));
PGPException, IOException {
Bundle returnData = new Bundle();
ArmoredOutputStream out = new ArmoredOutputStream(outStream);
out.setHeader("Version", getFullVersion(context));
int numKeys = 0;
for (int i = 0; i < masterKeyIds.length; ++i) {
updateProgress(progress, i * 100 / masterKeyIds.length, 100);
// try to get it as a PGPPublicKeyRing, if that fails try to get it as a SecretKeyRing
PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(context,
masterKeyIds[i]);
if (publicKeyRing != null) {
publicKeyRing.encode(out);
} else {
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByRowId(context,
masterKeyIds[i]);
if (secretKeyRing != null) { if (secretKeyRing != null) {
secretKeyRing.encode(out); secretKeyRing.encode(outSec);
} else {
continue;
}
} }
++numKeys; ++numKeys;
} }
out.close(); outSec.close();
}
returnData.putInt(ApgIntentService.RESULT_EXPORT, numKeys); returnData.putInt(ApgIntentService.RESULT_EXPORT, numKeys);
updateProgress(progress, R.string.progress_done, 100, 100); updateProgress(progress, R.string.progress_done, 100, 100);

View File

@ -420,16 +420,16 @@ public class ProviderHelper {
* @param queryUri * @param queryUri
* @return * @return
*/ */
private static ArrayList<Long> getKeyRingsRowIds(Context context, Uri queryUri) { private static ArrayList<Long> getKeyRingsMasterKeyIds(Context context, Uri queryUri) {
Cursor cursor = context.getContentResolver().query(queryUri, new String[] { KeyRings._ID }, Cursor cursor = context.getContentResolver().query(queryUri,
null, null, null); new String[] { KeyRings.MASTER_KEY_ID }, null, null, null);
ArrayList<Long> keyIds = new ArrayList<Long>(); ArrayList<Long> masterKeyIds = new ArrayList<Long>();
if (cursor != null) { if (cursor != null) {
int idCol = cursor.getColumnIndex(KeyRings._ID); int masterKeyIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
do { do {
keyIds.add(cursor.getLong(idCol)); masterKeyIds.add(cursor.getLong(masterKeyIdCol));
} while (cursor.moveToNext()); } while (cursor.moveToNext());
} }
} }
@ -438,7 +438,7 @@ public class ProviderHelper {
cursor.close(); cursor.close();
} }
return keyIds; return masterKeyIds;
} }
/** /**
@ -447,9 +447,9 @@ public class ProviderHelper {
* @param context * @param context
* @return * @return
*/ */
public static ArrayList<Long> getSecretKeyRingsRowIds(Context context) { public static ArrayList<Long> getSecretKeyRingsMasterKeyIds(Context context) {
Uri queryUri = KeyRings.buildSecretKeyRingsUri(); Uri queryUri = KeyRings.buildSecretKeyRingsUri();
return getKeyRingsRowIds(context, queryUri); return getKeyRingsMasterKeyIds(context, queryUri);
} }
/** /**
@ -458,9 +458,9 @@ public class ProviderHelper {
* @param context * @param context
* @return * @return
*/ */
public static ArrayList<Long> getPublicKeyRingsRowIds(Context context) { public static ArrayList<Long> getPublicKeyRingsMasterKeyIds(Context context) {
Uri queryUri = KeyRings.buildPublicKeyRingsUri(); Uri queryUri = KeyRings.buildPublicKeyRingsUri();
return getKeyRingsRowIds(context, queryUri); return getKeyRingsMasterKeyIds(context, queryUri);
} }
public static void deletePublicKeyRing(Context context, long rowId) { public static void deletePublicKeyRing(Context context, long rowId) {

View File

@ -144,7 +144,7 @@ public class ApgIntentService extends IntentService implements ProgressDialogUpd
public static final String EXPORT_FILENAME = "exportFilename"; public static final String EXPORT_FILENAME = "exportFilename";
public static final String EXPORT_KEY_TYPE = "exportKeyType"; public static final String EXPORT_KEY_TYPE = "exportKeyType";
public static final String EXPORT_ALL = "exportAll"; public static final String EXPORT_ALL = "exportAll";
public static final String EXPORT_KEY_RING_ROW_ID = "exportKeyRingId"; public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "exportKeyRingId";
// upload key // upload key
public static final String UPLOAD_KEY_SERVER = "uploadKeyServer"; public static final String UPLOAD_KEY_SERVER = "uploadKeyServer";
@ -691,9 +691,9 @@ public class ApgIntentService extends IntentService implements ProgressDialogUpd
String outputFile = data.getString(EXPORT_FILENAME); String outputFile = data.getString(EXPORT_FILENAME);
boolean exportAll = data.getBoolean(EXPORT_ALL); boolean exportAll = data.getBoolean(EXPORT_ALL);
long keyRingRowId = -1; long keyRingMasterKeyId = -1;
if (!exportAll) { if (!exportAll) {
keyRingRowId = data.getLong(EXPORT_KEY_RING_ROW_ID); keyRingMasterKeyId = data.getLong(EXPORT_KEY_RING_MASTER_KEY_ID);
} }
/* Operation */ /* Operation */
@ -706,21 +706,22 @@ public class ApgIntentService extends IntentService implements ProgressDialogUpd
// OutputStream // OutputStream
FileOutputStream outStream = new FileOutputStream(outputFile); FileOutputStream outStream = new FileOutputStream(outputFile);
ArrayList<Long> keyRingRowIds = new ArrayList<Long>(); ArrayList<Long> keyRingMasterKeyIds = new ArrayList<Long>();
if (exportAll) { if (exportAll) {
// get all key ring row ids based on export type // get all key ring row ids based on export type
if (keyType == Id.type.public_key) { if (keyType == Id.type.public_key) {
keyRingRowIds = ProviderHelper.getPublicKeyRingsRowIds(this); keyRingMasterKeyIds = ProviderHelper.getPublicKeyRingsMasterKeyIds(this);
} else { } else {
keyRingRowIds = ProviderHelper.getSecretKeyRingsRowIds(this); keyRingMasterKeyIds = ProviderHelper.getSecretKeyRingsMasterKeyIds(this);
} }
} else { } else {
keyRingRowIds.add(keyRingRowId); keyRingMasterKeyIds.add(keyRingMasterKeyId);
} }
Bundle resultData = new Bundle(); Bundle resultData = new Bundle();
resultData = PGPMain.exportKeyRings(this, keyRingRowIds, outStream, this); resultData = PGPMain.exportKeyRings(this, keyRingMasterKeyIds, keyType, outStream,
this);
sendMessageToHandler(ApgIntentServiceHandler.MESSAGE_OKAY, resultData); sendMessageToHandler(ApgIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) { } catch (Exception e) {

View File

@ -441,6 +441,7 @@ public class ImportKeysActivity extends SherlockFragmentActivity {
// mScannedContent = scanResult.getContents(); // mScannedContent = scanResult.getContents();
mImportData = scanResult.getContents().getBytes(); mImportData = scanResult.getContents().getBytes();
mImportFilename = null;
// mContentView.setText(mScannedContent); // mContentView.setText(mScannedContent);
// String[] bits = scanResult.getContents().split(","); // String[] bits = scanResult.getContents().split(",");

View File

@ -87,7 +87,6 @@ public class KeyListActivity extends SherlockFragmentActivity {
} }
} }
// if (searchString == null) { // if (searchString == null) {
// mFilterLayout.setVisibility(View.GONE); // mFilterLayout.setVisibility(View.GONE);
// } else { // } else {
@ -134,8 +133,8 @@ public class KeyListActivity extends SherlockFragmentActivity {
// TODO: reimplement! // TODO: reimplement!
// menu.add(3, Id.menu.option.search, 0, R.string.menu_search) // menu.add(3, Id.menu.option.search, 0, R.string.menu_search)
// .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); // .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0, Id.menu.option.import_from_file, 5, R.string.menu_importFromFile).setShowAsAction( menu.add(0, Id.menu.option.import_from_file, 5, R.string.menu_importFromFile)
MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(0, Id.menu.option.export_keys, 6, R.string.menu_exportKeys).setShowAsAction( menu.add(0, Id.menu.option.export_keys, 6, R.string.menu_exportKeys).setShowAsAction(
MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@ -178,10 +177,10 @@ public class KeyListActivity extends SherlockFragmentActivity {
/** /**
* Show dialog where to export keys * Show dialog where to export keys
* *
* @param keyRingRowId * @param keyRingMasterKeyId
* if -1 export all keys * if -1 export all keys
*/ */
public void showExportKeysDialog(final long keyRingRowId) { public void showExportKeysDialog(final long keyRingMasterKeyId) {
// Message is received after file is selected // Message is received after file is selected
Handler returnHandler = new Handler() { Handler returnHandler = new Handler() {
@Override @Override
@ -190,7 +189,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
Bundle data = message.getData(); Bundle data = message.getData();
mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
exportKeys(keyRingRowId); exportKeys(keyRingMasterKeyId);
} }
} }
}; };
@ -201,7 +200,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
public void run() { public void run() {
String title = null; String title = null;
if (keyRingRowId != -1) { if (keyRingMasterKeyId != -1) {
// single key export // single key export
title = getString(R.string.title_exportKey); title = getString(R.string.title_exportKey);
} else { } else {
@ -251,10 +250,10 @@ public class KeyListActivity extends SherlockFragmentActivity {
/** /**
* Export keys * Export keys
* *
* @param keyRingRowId * @param keyRingMasterKeyId
* if -1 export all keys * if -1 export all keys
*/ */
public void exportKeys(long keyRingRowId) { public void exportKeys(long keyRingMasterKeyId) {
Log.d(Constants.TAG, "exportKeys started"); Log.d(Constants.TAG, "exportKeys started");
// Send all information needed to service to export key in other thread // Send all information needed to service to export key in other thread
@ -268,10 +267,10 @@ public class KeyListActivity extends SherlockFragmentActivity {
data.putString(ApgIntentService.EXPORT_FILENAME, mExportFilename); data.putString(ApgIntentService.EXPORT_FILENAME, mExportFilename);
data.putInt(ApgIntentService.EXPORT_KEY_TYPE, mKeyType); data.putInt(ApgIntentService.EXPORT_KEY_TYPE, mKeyType);
if (keyRingRowId == -1) { if (keyRingMasterKeyId == -1) {
data.putBoolean(ApgIntentService.EXPORT_ALL, true); data.putBoolean(ApgIntentService.EXPORT_ALL, true);
} else { } else {
data.putLong(ApgIntentService.EXPORT_KEY_RING_ROW_ID, keyRingRowId); data.putLong(ApgIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, keyRingMasterKeyId);
} }
intent.putExtra(ApgIntentService.EXTRA_DATA, data); intent.putExtra(ApgIntentService.EXTRA_DATA, data);

View File

@ -19,6 +19,7 @@ package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.ui.widget.ExpandableListFragment; import org.thialfihar.android.apg.ui.widget.ExpandableListFragment;
import android.os.Bundle; import android.os.Bundle;
@ -66,7 +67,12 @@ public class KeyListFragment extends ExpandableListFragment {
switch (item.getItemId()) { switch (item.getItemId()) {
case Id.menu.export: case Id.menu.export:
mKeyListActivity.showExportKeysDialog(keyRingRowId); long masterKeyId = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId);
if (masterKeyId == -1) {
masterKeyId = ProviderHelper.getSecretMasterKeyId(mKeyListActivity, keyRingRowId);
}
mKeyListActivity.showExportKeysDialog(masterKeyId);
return true; return true;
case Id.menu.delete: case Id.menu.delete: