From 4eebeede2bb9724f7282cc9f8c2421f6f860e159 Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 13 Apr 2012 16:54:50 +0200 Subject: [PATCH] implemented secret keys without passphrase --- org_apg/res/layout/decrypt.xml | 7 ++- org_apg/res/values/strings.xml | 2 +- org_apg/src/org/apg/Apg.java | 26 ++++------- .../org/apg/AskForSecretKeyPassPhrase.java | 20 ++++++++- org_apg/src/org/apg/ui/DecryptActivity.java | 17 +++----- org_apg/src/org/apg/ui/EditKeyActivity.java | 43 ++++++++++++++----- .../src/org/apg/ui/SecretKeyListActivity.java | 17 +++----- org_apg/src/org/apg/util/Utils.java | 21 +++++++++ 8 files changed, 98 insertions(+), 55 deletions(-) diff --git a/org_apg/res/layout/decrypt.xml b/org_apg/res/layout/decrypt.xml index eccd4bf7a..d31c3bdec 100644 --- a/org_apg/res/layout/decrypt.xml +++ b/org_apg/res/layout/decrypt.xml @@ -25,15 +25,14 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:fillViewport="true" - android:paddingLeft="10dp" - android:paddingRight="10dp" > + android:fillViewport="true" > + android:paddingLeft="10dp" + android:paddingRight="10dp" > Key Server Update Export To Server - Share + Share with QR Code Scan QR Code Sign Key diff --git a/org_apg/src/org/apg/Apg.java b/org_apg/src/org/apg/Apg.java index dbe60e65e..97e5715d9 100644 --- a/org_apg/src/org/apg/Apg.java +++ b/org_apg/src/org/apg/Apg.java @@ -27,6 +27,7 @@ import org.apg.ui.widget.KeyEditor; import org.apg.ui.widget.SectionView; import org.apg.ui.widget.UserIdEditor; import org.apg.util.IterableIterator; +import org.apg.util.Utils; import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.BCPGOutputStream; @@ -155,6 +156,7 @@ public class Apg { public static final String EXTRA_BINARY = "binary"; public static final String EXTRA_KEY_SERVERS = "keyServers"; public static final String EXTRA_EXPECTED_FINGERPRINT = "expectedFingerprint"; + public static final String EXTRA_NO_PASSPHRASE = "noPassphrase"; public static final String AUTHORITY = DataProvider.AUTHORITY; @@ -374,18 +376,6 @@ public class Apg { return secretKey; } - private static long getNumDaysBetween(GregorianCalendar first, GregorianCalendar second) { - GregorianCalendar tmp = new GregorianCalendar(); - tmp.setTime(first.getTime()); - long numDays = (second.getTimeInMillis() - first.getTimeInMillis()) / 1000 / 86400; - tmp.add(Calendar.DAY_OF_MONTH, (int) numDays); - while (tmp.before(second)) { - tmp.add(Calendar.DAY_OF_MONTH, 1); - ++numDays; - } - return numDays; - } - public static void buildSecretKey(Activity context, SectionView userIdsView, SectionView keysView, String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException, @@ -509,7 +499,7 @@ public class Apg { GregorianCalendar creationDate = new GregorianCalendar(); creationDate.setTime(getCreationDate(masterKey)); GregorianCalendar expiryDate = keyEditor.getExpiryDate(); - long numDays = getNumDaysBetween(creationDate, expiryDate); + long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); if (numDays <= 0) { throw new GeneralException( context.getString(R.string.error_expiryMustComeAfterCreation)); @@ -517,8 +507,10 @@ public class Apg { hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400); } - if (progress != null) + if (progress != null) { progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100); + } + PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair, mainUserId, PGPEncryptedData.CAST5, newPassPhrase.toCharArray(), hashedPacketsGen.generate(), unhashedPacketsGen.generate(), new SecureRandom(), @@ -558,7 +550,7 @@ public class Apg { GregorianCalendar creationDate = new GregorianCalendar(); creationDate.setTime(getCreationDate(masterKey)); GregorianCalendar expiryDate = keyEditor.getExpiryDate(); - long numDays = getNumDaysBetween(creationDate, expiryDate); + long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); if (numDays <= 0) { throw new GeneralException( context.getString(R.string.error_expiryMustComeAfterCreation)); @@ -2202,7 +2194,7 @@ public class Apg { return false; } } catch (NameNotFoundException e) { - // unpossible! + // impossible! return false; } } @@ -2216,7 +2208,7 @@ public class Apg { VERSION = pi.versionName; return VERSION; } catch (NameNotFoundException e) { - // unpossible! + // impossible! return "0.0.0"; } } diff --git a/org_apg/src/org/apg/AskForSecretKeyPassPhrase.java b/org_apg/src/org/apg/AskForSecretKeyPassPhrase.java index 5c55321c6..ac3b678d8 100644 --- a/org_apg/src/org/apg/AskForSecretKeyPassPhrase.java +++ b/org_apg/src/org/apg/AskForSecretKeyPassPhrase.java @@ -28,6 +28,7 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; @@ -86,7 +87,7 @@ public class AskForSecretKeyPassPhrase { alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { activity.removeDialog(Id.dialog.pass_phrase); - String passPhrase = "" + input.getText(); + String passPhrase = input.getText().toString(); long keyId; if (secretKey != null) { try { @@ -116,6 +117,23 @@ public class AskForSecretKeyPassPhrase { } }); + // check if the key has no passphrase + if (secretKey != null) { + try { + Log.d("APG", "check if key has no passphrase..."); + PGPPrivateKey testKey = secretKey.extractPrivateKey("".toCharArray(), + new BouncyCastleProvider()); + if (testKey != null) { + Log.d("APG", "Key has no passphrase!"); + + cb.passPhraseCallback(secretKey.getKeyID(), null); + + return null; + } + } catch (PGPException e) { + + } + } return alert.create(); } } diff --git a/org_apg/src/org/apg/ui/DecryptActivity.java b/org_apg/src/org/apg/ui/DecryptActivity.java index a1a533763..575a08c8c 100644 --- a/org_apg/src/org/apg/ui/DecryptActivity.java +++ b/org_apg/src/org/apg/ui/DecryptActivity.java @@ -118,16 +118,12 @@ public class DecryptActivity extends BaseActivity { public boolean onCreateOptionsMenu(Menu menu) { if (mDecryptEnabled) { - menu.add(1, Id.menu.option.decrypt, 0, mDecryptString) - // .setIcon(R.drawable.ic_menu_encrypt) - .setShowAsAction( - MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(1, Id.menu.option.decrypt, 0, mDecryptString).setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } if (mReplyEnabled) { - menu.add(1, Id.menu.option.reply, 1, mReplyString) - // .setIcon(R.drawable.ic_menu_decrypt) - .setShowAsAction( - MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(1, Id.menu.option.reply, 1, mReplyString).setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } return true; @@ -275,9 +271,8 @@ public class DecryptActivity extends BaseActivity { // replace non breakable spaces textData = textData.replaceAll("\\xa0", " "); mMessage.setText(textData); + mDecryptString = getString(R.string.btn_verify); - // mDecryptButton.setText(R.string.btn_verify); - // build new action bar invalidateOptionsMenu(); } else { @@ -399,8 +394,6 @@ public class DecryptActivity extends BaseActivity { if (mSource.getCurrentView().getId() == R.id.sourceMessage && (mMessage.getText().length() > 0 || mData != null || mContentUri != null)) { - // mDecryptButton.performClick(); - // TODO: why was it performClick()??? decryptClicked(); } } diff --git a/org_apg/src/org/apg/ui/EditKeyActivity.java b/org_apg/src/org/apg/ui/EditKeyActivity.java index e00cb7d24..3809f160d 100644 --- a/org_apg/src/org/apg/ui/EditKeyActivity.java +++ b/org_apg/src/org/apg/ui/EditKeyActivity.java @@ -38,7 +38,6 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.os.Message; import android.view.LayoutInflater; @@ -49,7 +48,6 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.TableRow; import android.widget.Toast; import android.widget.CompoundButton.OnCheckedChangeListener; @@ -72,6 +70,8 @@ public class EditKeyActivity extends BaseActivity { private Button mChangePassPhrase; + private CheckBox mNoPassphrase; + @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(1, Id.menu.option.cancel, 0, R.string.btn_doNotSave).setShowAsAction( @@ -152,6 +152,14 @@ public class EditKeyActivity extends BaseActivity { if (extras.containsKey(Apg.EXTRA_USER_IDS)) { userIds.add(extras.getString(Apg.EXTRA_USER_IDS)); } + + // if userId is given, prefill the fields + if (extras.containsKey(Apg.EXTRA_NO_PASSPHRASE)) { + boolean noPassphrase = extras.getBoolean(Apg.EXTRA_NO_PASSPHRASE); + if (noPassphrase) { + mCurrentPassPhrase = ""; + } + } } mChangePassPhrase = (Button) findViewById(R.id.edit_key_btn_change_pass_phrase); @@ -162,12 +170,15 @@ public class EditKeyActivity extends BaseActivity { }); // disable passphrase when no passphrase checkobox is checked! - final CheckBox noPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase); - noPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() { + mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase); + mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { + // remove passphrase + mNewPassPhrase = null; + mChangePassPhrase.setVisibility(View.GONE); } else { mChangePassPhrase.setVisibility(View.VISIBLE); @@ -194,6 +205,12 @@ public class EditKeyActivity extends BaseActivity { mCurrentPassPhrase = ""; } + if (mCurrentPassPhrase.equals("")) { + // check "no passphrase" checkbox and remove button + mNoPassphrase.setChecked(true); + mChangePassPhrase.setVisibility(View.GONE); + } + updatePassPhraseButtonText(); } @@ -204,9 +221,15 @@ public class EditKeyActivity extends BaseActivity { return ((KeyEditor) mKeys.getEditors().getChildAt(0)).getValue().getKeyID(); } - public boolean havePassPhrase() { - return (!mCurrentPassPhrase.equals("")) - || (mNewPassPhrase != null && !mNewPassPhrase.equals("")); + public boolean isPassphraseSet() { + if (mNoPassphrase.isChecked()) { + return true; + } else if ((!mCurrentPassPhrase.equals("")) + || (mNewPassPhrase != null && !mNewPassPhrase.equals(""))) { + return true; + } else { + return false; + } } @Override @@ -215,7 +238,7 @@ public class EditKeyActivity extends BaseActivity { case Id.dialog.new_pass_phrase: { AlertDialog.Builder alert = new AlertDialog.Builder(this); - if (havePassPhrase()) { + if (isPassphraseSet()) { alert.setTitle(R.string.title_changePassPhrase); } else { alert.setTitle(R.string.title_setPassPhrase); @@ -266,7 +289,7 @@ public class EditKeyActivity extends BaseActivity { } private void saveClicked() { - if (!havePassPhrase()) { + if (!isPassphraseSet()) { Toast.makeText(this, R.string.setAPassPhrase, Toast.LENGTH_SHORT).show(); return; } @@ -333,7 +356,7 @@ public class EditKeyActivity extends BaseActivity { } private void updatePassPhraseButtonText() { - mChangePassPhrase.setText(havePassPhrase() ? R.string.btn_changePassPhrase + mChangePassPhrase.setText(isPassphraseSet() ? R.string.btn_changePassPhrase : R.string.btn_setPassPhrase); } } diff --git a/org_apg/src/org/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/apg/ui/SecretKeyListActivity.java index 2e46ebcd4..0e6d78c03 100644 --- a/org_apg/src/org/apg/ui/SecretKeyListActivity.java +++ b/org_apg/src/org/apg/ui/SecretKeyListActivity.java @@ -49,15 +49,13 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(3, Id.menu.option.search, 0, R.string.menu_search) - .setIcon(R.drawable.ic_menu_search) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - menu.add(1, Id.menu.option.create, 1, R.string.menu_createKey) - .setShowAsAction( - MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); - menu.add(0, Id.menu.option.import_keys, 2, R.string.menu_importKeys) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); - menu.add(0, Id.menu.option.export_keys, 3, R.string.menu_exportKeys) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + menu.add(1, Id.menu.option.create, 1, R.string.menu_createKey).setShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(0, Id.menu.option.import_keys, 2, R.string.menu_importKeys).setShowAsAction( + MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(0, Id.menu.option.export_keys, 3, R.string.menu_exportKeys).setShowAsAction( + MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; } @@ -114,7 +112,6 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()) .getGroupId(mSelectedItem); String msg = keyId + "," + Apg.getFingerPrint(keyId); - ; new IntentIntegrator(this).shareText(msg); } diff --git a/org_apg/src/org/apg/util/Utils.java b/org_apg/src/org/apg/util/Utils.java index 45b18afd1..83a65213d 100644 --- a/org_apg/src/org/apg/util/Utils.java +++ b/org_apg/src/org/apg/util/Utils.java @@ -19,6 +19,8 @@ package org.apg.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Calendar; +import java.util.GregorianCalendar; import android.content.Context; @@ -51,4 +53,23 @@ public class Utils { return stream.toString(); } + /** + * Return the number if days between two dates + * + * @param first + * @param second + * @return number of days + */ + public static long getNumDaysBetween(GregorianCalendar first, GregorianCalendar second) { + GregorianCalendar tmp = new GregorianCalendar(); + tmp.setTime(first.getTime()); + long numDays = (second.getTimeInMillis() - first.getTimeInMillis()) / 1000 / 86400; + tmp.add(Calendar.DAY_OF_MONTH, (int) numDays); + while (tmp.before(second)) { + tmp.add(Calendar.DAY_OF_MONTH, 1); + ++numDays; + } + return numDays; + } + }