aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik <dominik@dominikschuermann.de>2012-09-11 19:56:54 +0200
committerDominik <dominik@dominikschuermann.de>2012-09-11 19:56:54 +0200
commit4b8400685a62afa0f4cb21940e9583d21886535b (patch)
tree662e79ac2e6e9273d62270251b738c04b971262e
parentbe49597882a8170ed6244c0f20c375cd525a883d (diff)
downloadopen-keychain-4b8400685a62afa0f4cb21940e9583d21886535b.tar.gz
open-keychain-4b8400685a62afa0f4cb21940e9583d21886535b.tar.bz2
open-keychain-4b8400685a62afa0f4cb21940e9583d21886535b.zip
completly new PasswordCacheService (more energy efficient), reworked Password dialogs
-rw-r--r--org_apg/AndroidManifest.xml35
-rw-r--r--org_apg/res/layout/passphrase.xml1
-rw-r--r--org_apg/res/layout/passphrase_repeat.xml1
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ApgApplication.java3
-rw-r--r--org_apg/src/org/thialfihar/android/apg/deprecated/AskForPassphrase.java156
-rw-r--r--org_apg/src/org/thialfihar/android/apg/deprecated/BaseActivity.java12
-rw-r--r--org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java67
-rw-r--r--org_apg/src/org/thialfihar/android/apg/service/ApgService.java66
-rw-r--r--org_apg/src/org/thialfihar/android/apg/service/CachedPassphrase.java22
-rw-r--r--org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java205
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java5
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java6
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java3
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java8
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java5
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java62
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/dialog/SetPassphraseDialogFragment.java48
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java4
-rw-r--r--org_apg/src/org/thialfihar/android/apg/util/KeyServer.java1
19 files changed, 363 insertions, 347 deletions
diff --git a/org_apg/AndroidManifest.xml b/org_apg/AndroidManifest.xml
index 2a1e0bc4f..70cc98c8d 100644
--- a/org_apg/AndroidManifest.xml
+++ b/org_apg/AndroidManifest.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
+ Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,7 +50,7 @@
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" >
<activity
android:name=".ui.MainActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -59,7 +60,7 @@
</activity>
<activity
android:name=".ui.PublicKeyListActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_managePublicKeys"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
@@ -73,7 +74,7 @@
</activity>
<activity
android:name=".ui.SecretKeyListActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_manageSecretKeys"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
@@ -87,7 +88,7 @@
</activity>
<activity
android:name=".ui.EditKeyActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_editKey"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
@@ -100,7 +101,7 @@
</activity>
<activity
android:name=".ui.SelectPublicKeyListActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_selectRecipients"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
@@ -119,7 +120,7 @@
</activity>
<activity
android:name=".ui.SelectSecretKeyListActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_selectSignature"
android:launchMode="singleTop" >
<intent-filter>
@@ -137,7 +138,7 @@
</activity>
<activity
android:name=".ui.EncryptActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_encrypt"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
@@ -154,7 +155,7 @@
</activity>
<activity
android:name=".ui.DecryptActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_decrypt"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
@@ -170,7 +171,7 @@
</activity>
<activity
android:name=".deprecated.GeneralActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog" >
<intent-filter>
@@ -202,39 +203,39 @@
</activity>
<activity
android:name=".ui.MailListActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_mailInbox" />
<activity
android:name=".ui.KeyServerQueryActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_keyServerQuery" />
<activity
android:name=".ui.KeyServerUploadActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_sendKey" />
<activity
android:name=".ui.PreferencesActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_preferences" />
<activity
android:name=".ui.PreferencesKeyServerActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_keyServerPreference"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".ui.SignKeyActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_signKey" />
<activity
android:name=".ui.ImportFromQRCodeActivity"
- android:configChanges="keyboardHidden|orientation|keyboard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_importFromQRCode" />
<activity
android:name=".ui.HelpActivity"
android:label="@string/title_help" />
- <service android:name=".service.password.PassphraseCacheService" />
+ <service android:name=".service.PassphraseCacheService" />
<service android:name=".service.ApgService" />
<!-- TODO: need to be moved into new service model -->
diff --git a/org_apg/res/layout/passphrase.xml b/org_apg/res/layout/passphrase.xml
index d4a498532..fc9cb1710 100644
--- a/org_apg/res/layout/passphrase.xml
+++ b/org_apg/res/layout/passphrase.xml
@@ -33,6 +33,7 @@
android:id="@+id/passphrase_passphrase"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
+ android:imeOptions="actionDone"
android:inputType="textPassword"
android:padding="4dp" />
diff --git a/org_apg/res/layout/passphrase_repeat.xml b/org_apg/res/layout/passphrase_repeat.xml
index 73a085588..8f1d42aac 100644
--- a/org_apg/res/layout/passphrase_repeat.xml
+++ b/org_apg/res/layout/passphrase_repeat.xml
@@ -54,6 +54,7 @@
android:id="@+id/passphrase_passphrase_again"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
+ android:imeOptions="actionDone"
android:inputType="textPassword"
android:padding="4dp" />
</TableRow>
diff --git a/org_apg/src/org/thialfihar/android/apg/ApgApplication.java b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
index de3c1e745..359aa08cf 100644
--- a/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
+++ b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
@@ -38,7 +38,8 @@ public class ApgApplication extends Application {
super.onCreate();
/* Start passphrase cache service */
- PassphraseCacheService.startCacheService(this);
+ // TODO: not needed anymore!
+ // PassphraseCacheService.startCacheService(this);
// TODO: Do it better than this!
// this initializes the database to be used in PGPMain
diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/AskForPassphrase.java b/org_apg/src/org/thialfihar/android/apg/deprecated/AskForPassphrase.java
deleted file mode 100644
index 90cd39176..000000000
--- a/org_apg/src/org/thialfihar/android/apg/deprecated/AskForPassphrase.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.thialfihar.android.apg.deprecated;
-
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.openpgp.PGPException;
-import org.spongycastle.openpgp.PGPPrivateKey;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.thialfihar.android.apg.Id;
-import org.thialfihar.android.apg.R;
-import org.thialfihar.android.apg.helper.PGPHelper;
-import org.thialfihar.android.apg.helper.PGPMain;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import org.thialfihar.android.apg.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * TODO:
- *
- * - Use new PassphraseDialogFragment!
- *
- *
- */
-public class AskForPassphrase {
- public static interface PassPhraseCallbackInterface {
- void passPhraseCallback(long keyId, String passPhrase);
- }
-
- public static Dialog createDialog(Activity context, long secretKeyId,
- PassPhraseCallbackInterface callback) {
- AlertDialog.Builder alert = new AlertDialog.Builder(context);
-
- alert.setTitle(R.string.title_authentication);
-
- final PGPSecretKey secretKey;
- final Activity activity = context;
-
- if (secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none) {
- secretKey = null;
- alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption));
- } else {
- secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
- if (secretKey == null) {
- alert.setTitle(R.string.title_keyNotFound);
- alert.setMessage(context.getString(R.string.keyNotFound, secretKeyId));
- alert.setPositiveButton(android.R.string.ok, new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- activity.removeDialog(Id.dialog.pass_phrase);
- }
- });
- alert.setCancelable(false);
- return alert.create();
- }
- String userId = PGPHelper.getMainUserIdSafe(context, secretKey);
- alert.setMessage(context.getString(R.string.passPhraseFor, userId));
- }
-
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.passphrase, null);
- final EditText input = (EditText) view.findViewById(R.id.passphrase_passphrase);
-
- final TextView labelNotUsed = (TextView) view
- .findViewById(R.id.passphrase_label_passphrase_again);
- labelNotUsed.setVisibility(View.GONE);
- final EditText inputNotUsed = (EditText) view
- .findViewById(R.id.passphrase_passphrase_again);
- inputNotUsed.setVisibility(View.GONE);
-
- alert.setView(view);
-
- final PassPhraseCallbackInterface cb = callback;
- 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().toString();
- long keyId;
- if (secretKey != null) {
- try {
- PGPPrivateKey testKey = secretKey.extractPrivateKey(
- passPhrase.toCharArray(), new BouncyCastleProvider());
- if (testKey == null) {
- Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
- Toast.LENGTH_SHORT).show();
- return;
- }
- } catch (PGPException e) {
- Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
- .show();
- return;
- }
- keyId = secretKey.getKeyID();
- } else {
- keyId = Id.key.symmetric;
- }
-
- // cache again
- PGPMain.setCachedPassPhrase(keyId, passPhrase);
- // return by callback
- cb.passPhraseCallback(keyId, passPhrase);
- }
- });
-
- alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- activity.removeDialog(Id.dialog.pass_phrase);
- }
- });
-
- // 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!");
-
- // cache null
- PGPMain.setCachedPassPhrase(secretKey.getKeyID(), null);
- // return by callback
- cb.passPhraseCallback(secretKey.getKeyID(), null);
-
- return null;
- }
- } catch (PGPException e) {
-
- }
- }
- return alert.create();
- }
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/BaseActivity.java b/org_apg/src/org/thialfihar/android/apg/deprecated/BaseActivity.java
index 2d1cfcf6c..09638e478 100644
--- a/org_apg/src/org/thialfihar/android/apg/deprecated/BaseActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/deprecated/BaseActivity.java
@@ -42,7 +42,7 @@ import android.os.Handler;
import android.os.Message;
public class BaseActivity extends SherlockFragmentActivity implements Runnable,
- ProgressDialogUpdater, AskForPassphrase.PassPhraseCallbackInterface {
+ ProgressDialogUpdater {
private ProgressDialog mProgressDialog = null;
// private PausableThread mRunningThread = null;
@@ -363,11 +363,11 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
//
// Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
// }
-
- public void passPhraseCallback(long keyId, String passPhrase) {
- // TODO: Not needed anymore, now implemented in AskForSecretKeyPass
- PGPMain.setCachedPassPhrase(keyId, passPhrase);
- }
+ //
+ // public void passPhraseCallback(long keyId, String passPhrase) {
+ // // TODO: Not needed anymore, now implemented in AskForSecretKeyPass
+ // PGPMain.setCachedPassPhrase(keyId, passPhrase);
+ // }
// public void sendMessage(Message msg) {
// mHandler.sendMessage(msg);
diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
index 2fd63bda1..887b4c8f6 100644
--- a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
+++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
@@ -78,7 +78,6 @@ import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
import org.thialfihar.android.apg.service.ApgService;
-import org.thialfihar.android.apg.service.CachedPassphrase;
import org.thialfihar.android.apg.util.HkpKeyServer;
import org.thialfihar.android.apg.util.InputData;
import org.thialfihar.android.apg.util.PositionAwareInputStream;
@@ -121,9 +120,7 @@ import java.security.Security;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Date;
-import java.util.HashMap;
import java.util.Iterator;
-import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
@@ -185,7 +182,6 @@ public class PGPMain {
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
Pattern.DOTALL);
- private static HashMap<Long, CachedPassphrase> mPassPhraseCache = new HashMap<Long, CachedPassphrase>();
private static String mEditPassPhrase = null;
private static Database mDatabase = null;
@@ -224,58 +220,6 @@ public class PGPMain {
return mEditPassPhrase;
}
- public static void setCachedPassPhrase(long keyId, String passPhrase) {
- mPassPhraseCache.put(keyId, new CachedPassphrase(new Date().getTime(), passPhrase));
- }
-
- public static String getCachedPassPhrase(long keyId) {
- long realId = keyId;
- if (realId != Id.key.symmetric) {
- PGPSecretKeyRing keyRing = getSecretKeyRing(keyId);
- if (keyRing == null) {
- return null;
- }
- PGPSecretKey masterKey = PGPHelper.getMasterKey(keyRing);
- if (masterKey == null) {
- return null;
- }
- realId = masterKey.getKeyID();
- }
- CachedPassphrase cpp = mPassPhraseCache.get(realId);
- if (cpp == null) {
- return null;
- }
- // set it again to reset the cache life cycle
- setCachedPassPhrase(realId, cpp.passPhrase);
- return cpp.passPhrase;
- }
-
- public static int cleanUpCache(int ttl, int initialDelay) {
- int delay = initialDelay;
- long realTtl = ttl * 1000;
- long now = new Date().getTime();
- Vector<Long> oldKeys = new Vector<Long>();
- for (Map.Entry<Long, CachedPassphrase> pair : mPassPhraseCache.entrySet()) {
- long lived = now - pair.getValue().timestamp;
- if (lived >= realTtl) {
- oldKeys.add(pair.getKey());
- } else {
- // see, whether the remaining time for this cache entry improves our
- // check delay
- long nextCheck = realTtl - lived + 1000;
- if (nextCheck < delay) {
- delay = (int) nextCheck;
- }
- }
- }
-
- for (long keyId : oldKeys) {
- mPassPhraseCache.remove(keyId);
- }
-
- return delay;
- }
-
/**
* Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
* when this key is the new masterkey. If a masterkey is supplied in the parameters
@@ -1268,11 +1212,10 @@ public class PGPMain {
progress.setProgress(R.string.progress_done, 100, 100);
}
- public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId)
- throws GeneralException, NoSuchAlgorithmException, NoSuchProviderException,
- PGPException, SignatureException {
- String signaturePassPhrase = PGPMain.getCachedPassPhrase(masterKeyId);
- if (signaturePassPhrase == null || signaturePassPhrase.length() <= 0) {
+ public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId,
+ String passphrase) throws GeneralException, NoSuchAlgorithmException,
+ NoSuchProviderException, PGPException, SignatureException {
+ if (passphrase == null || passphrase.length() <= 0) {
throw new GeneralException("Unable to obtain passphrase");
} else {
PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId);
@@ -1283,7 +1226,7 @@ public class PGPMain {
}
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray());
+ BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) {
throw new GeneralException(
diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
index 43987ccbc..624572b7b 100644
--- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
+++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
@@ -70,6 +70,25 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
public static final String EXTRA_ACTION = "action";
public static final String EXTRA_DATA = "data";
+ /* possible EXTRA_ACTIONs */
+ public static final int ACTION_ENCRYPT_SIGN = 10;
+
+ public static final int ACTION_DECRYPT_VERIFY = 20;
+
+ public static final int ACTION_SAVE_KEYRING = 30;
+ public static final int ACTION_GENERATE_KEY = 31;
+ public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 32;
+
+ public static final int ACTION_DELETE_FILE_SECURELY = 40;
+
+ public static final int ACTION_IMPORT_KEY = 50;
+ public static final int ACTION_EXPORT_KEY = 51;
+
+ public static final int ACTION_UPLOAD_KEY = 60;
+ public static final int ACTION_QUERY_KEY = 61;
+
+ public static final int ACTION_SIGN_KEY = 70;
+
/* keys for data bundle */
// encrypt, decrypt, import export
@@ -143,25 +162,6 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
public static final String SIGN_KEY_MASTER_KEY_ID = "signKeyMasterKeyId";
public static final String SIGN_KEY_PUB_KEY_ID = "signKeyPubKeyId";
- /* possible EXTRA_ACTIONs */
- public static final int ACTION_ENCRYPT_SIGN = 10;
-
- public static final int ACTION_DECRYPT_VERIFY = 20;
-
- public static final int ACTION_SAVE_KEYRING = 30;
- public static final int ACTION_GENERATE_KEY = 31;
- public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 32;
-
- public static final int ACTION_DELETE_FILE_SECURELY = 40;
-
- public static final int ACTION_IMPORT_KEY = 50;
- public static final int ACTION_EXPORT_KEY = 51;
-
- public static final int ACTION_UPLOAD_KEY = 60;
- public static final int ACTION_QUERY_KEY = 61;
-
- public static final int ACTION_SIGN_KEY = 70;
-
/* possible data keys as result send over messenger */
// keys
public static final String RESULT_NEW_KEY = "newKey";
@@ -320,19 +320,21 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
if (generateSignature) {
Log.d(Constants.TAG, "generating signature...");
PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, false,
- secretKeyId, PGPMain.getCachedPassPhrase(secretKeyId), Preferences
- .getPreferences(this).getDefaultHashAlgorithm(), Preferences
- .getPreferences(this).getForceV3Signatures(), this);
+ secretKeyId, PassphraseCacheService.getCachedPassphrase(this,
+ secretKeyId), Preferences.getPreferences(this)
+ .getDefaultHashAlgorithm(), Preferences.getPreferences(this)
+ .getForceV3Signatures(), this);
} else if (signOnly) {
Log.d(Constants.TAG, "sign only...");
- PGPMain.signText(this, inputData, outStream, secretKeyId, PGPMain
- .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this)
- .getDefaultHashAlgorithm(), Preferences.getPreferences(this)
- .getForceV3Signatures(), this);
+ PGPMain.signText(this, inputData, outStream, secretKeyId,
+ PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
+ Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
+ .getPreferences(this).getForceV3Signatures(), this);
} else {
Log.d(Constants.TAG, "encrypt...");
PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
- signatureKeyId, PGPMain.getCachedPassPhrase(signatureKeyId), this,
+ signatureKeyId,
+ PassphraseCacheService.getCachedPassphrase(this, signatureKeyId), this,
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
@@ -478,7 +480,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
this);
} else {
resultData = PGPMain.decrypt(this, inputData, outStream,
- PGPMain.getCachedPassPhrase(secretKeyId), this,
+ PassphraseCacheService.getCachedPassphrase(this, secretKeyId), this,
assumeSymmetricEncryption);
}
@@ -539,7 +541,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
/* Operation */
PGPMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
newPassPhrase, this);
- PGPMain.setCachedPassPhrase(masterKeyId, newPassPhrase);
+ PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
/* Output */
sendMessageToHandler(ApgServiceHandler.MESSAGE_OKAY);
@@ -798,7 +800,11 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID);
/* Operation */
- PGPPublicKeyRing signedPubKeyRing = PGPMain.signKey(this, masterKeyId, pubKeyId);
+ String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this,
+ masterKeyId);
+
+ PGPPublicKeyRing signedPubKeyRing = PGPMain.signKey(this, masterKeyId, pubKeyId,
+ signaturePassPhrase);
// store the signed key in our local cache
int retval = PGPMain.storeKeyRingInCache(signedPubKeyRing);
diff --git a/org_apg/src/org/thialfihar/android/apg/service/CachedPassphrase.java b/org_apg/src/org/thialfihar/android/apg/service/CachedPassphrase.java
index 0467bc2c5..0631bd6fa 100644
--- a/org_apg/src/org/thialfihar/android/apg/service/CachedPassphrase.java
+++ b/org_apg/src/org/thialfihar/android/apg/service/CachedPassphrase.java
@@ -15,19 +15,27 @@
package org.thialfihar.android.apg.service;
public class CachedPassphrase {
- public final long timestamp;
- public final String passPhrase;
+ private final long timestamp;
+ private final String passphrase;
public CachedPassphrase(long timestamp, String passPhrase) {
super();
this.timestamp = timestamp;
- this.passPhrase = passPhrase;
+ this.passphrase = passPhrase;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public String getPassphrase() {
+ return passphrase;
}
@Override
public int hashCode() {
int hc1 = (int) (this.timestamp & 0xffffffff);
- int hc2 = (this.passPhrase == null ? 0 : this.passPhrase.hashCode());
+ int hc2 = (this.passphrase == null ? 0 : this.passphrase.hashCode());
return (hc1 + hc2) * hc2 + hc1;
}
@@ -42,12 +50,12 @@ public class CachedPassphrase {
return false;
}
- if (passPhrase != o.passPhrase) {
- if (passPhrase == null || o.passPhrase == null) {
+ if (passphrase != o.passphrase) {
+ if (passphrase == null || o.passphrase == null) {
return false;
}
- if (!passPhrase.equals(o.passPhrase)) {
+ if (!passphrase.equals(o.passphrase)) {
return false;
}
}
diff --git a/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java b/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java
index 4d004ebfd..1a843b3fd 100644
--- a/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java
+++ b/org_apg/src/org/thialfihar/android/apg/service/PassphraseCacheService.java
@@ -1,4 +1,6 @@
/*
+ * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -14,90 +16,211 @@
package org.thialfihar.android.apg.service;
+import java.util.HashMap;
+
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.thialfihar.android.apg.Constants;
+import org.thialfihar.android.apg.Id;
+import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.Preferences;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.app.Service;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Binder;
-import android.os.Handler;
import android.os.IBinder;
+import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
public class PassphraseCacheService extends Service {
- private final IBinder mBinder = new LocalBinder();
+ public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX
+ + "PASSPHRASE_CACHE_SERVICE";
public static final String EXTRA_TTL = "ttl";
+ public static final String EXTRA_KEY_ID = "keyId";
+ public static final String EXTRA_PASSPHRASE = "passphrase";
+
+ private static final int REQUEST_ID = 0;
+ private static final long DEFAULT_TTL = 15;
+
+ private BroadcastReceiver mIntentReceiver;
+
+ // TODO: This is static to be easily retrieved by getCachedPassphrase()
+ // To avoid static we would need a messenger from the service back to the activity?
+ private static HashMap<Long, CachedPassphrase> mPassphraseCache = new HashMap<Long, CachedPassphrase>();
+
+ /**
+ * This caches a new passphrase by sending a new command to the service. An android service is
+ * only run once. Thus when it is already started new commands just add new BroadcastReceivers
+ * for cached passphrases
+ *
+ * @param context
+ * @param keyId
+ * @param passphrase
+ */
+ public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
+ Log.d(Constants.TAG, "cacheNewPassphrase() for " + keyId);
- public static void startCacheService(Context context) {
Intent intent = new Intent(context, PassphraseCacheService.class);
- intent.putExtra(PassphraseCacheService.EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
+ intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
+ intent.putExtra(EXTRA_PASSPHRASE, passphrase);
+ intent.putExtra(EXTRA_KEY_ID, keyId);
+
context.startService(intent);
}
- private int mPassPhraseCacheTtl = 15;
- private Handler mCacheHandler = new Handler();
- private Runnable mCacheTask = new Runnable() {
- public void run() {
- // check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15),
- // and makes sure the longest a pass phrase survives in the cache is 1.5 * ttl
- int delay = mPassPhraseCacheTtl * 1000 / 2;
- // also make sure the delay is not longer than one minute
- if (delay > 60000) {
- delay = 60000;
+ /**
+ * Gets a cached passphrase from memory
+ *
+ * @param context
+ * @param keyId
+ * @return
+ */
+ public static String getCachedPassphrase(Context context, long keyId) {
+ // try to get real key id
+ long realId = keyId;
+ if (realId != Id.key.symmetric) {
+ PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(keyId);
+ if (keyRing == null) {
+ return null;
}
-
- delay = PGPMain.cleanUpCache(mPassPhraseCacheTtl, delay);
- // don't check too often, even if we were close
- if (delay < 5000) {
- delay = 5000;
+ PGPSecretKey masterKey = PGPHelper.getMasterKey(keyRing);
+ if (masterKey == null) {
+ return null;
}
+ realId = masterKey.getKeyID();
+ }
- mCacheHandler.postDelayed(this, delay);
+ // get cached passphrase
+ CachedPassphrase cpp = mPassphraseCache.get(realId);
+ if (cpp == null) {
+ return null;
}
- };
+ // set it again to reset the cache life cycle
+ addCachedPassphrase(context, realId, cpp.getPassphrase());
- static private boolean mIsRunning = false;
+ return cpp.getPassphrase();
+ }
- @Override
- public void onCreate() {
- super.onCreate();
+ /**
+ * Register BroadcastReceiver that is unregistered when service is destroyed. This
+ * BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to timeout
+ * passphrases in memory.
+ */
+ private void registerReceiver() {
+ if (mIntentReceiver == null) {
+ mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
+ long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
+ timeout(context, keyId);
+ }
+ }
+ };
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
+ LocalBroadcastManager.getInstance(this).registerReceiver(mIntentReceiver, filter);
+ }
+ }
- mIsRunning = true;
+ /**
+ * Build pending intent that is executed by alarm manager when one passphrase times out
+ *
+ * @param context
+ * @param keyId
+ * @return
+ */
+ private static PendingIntent buildIntent(Context context, long keyId) {
+ Intent intent = new Intent(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
+ intent.putExtra(EXTRA_KEY_ID, keyId);
+ PendingIntent sender = PendingIntent.getBroadcast(context, REQUEST_ID, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ return sender;
}
@Override
- public void onDestroy() {
- super.onDestroy();
- mIsRunning = false;
+ public void onCreate() {
+ Log.d(Constants.TAG, "PassphraseCacheService created!");
}
+ /**
+ * Executed when service is started by intent
+ */
@Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(Constants.TAG, "PassphraseCacheService started");
+
+ // register broadcastreceiver
+ registerReceiver();
if (intent != null) {
- mPassPhraseCacheTtl = intent.getIntExtra(EXTRA_TTL, 15);
+ long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL);
+ long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
+ String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
+
+ Log.d(Constants.TAG, "received intent with keyId: " + keyId + ", ttl: " + ttl);
+
+ // add keyId and passphrase to memory
+ mPassphraseCache.put(keyId,
+ new CachedPassphrase(System.currentTimeMillis(), passphrase));
+
+ // register new alarm with keyId for this passphrase
+ long triggerTime = System.currentTimeMillis() + ttl;
+ AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
+ am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId));
}
- if (mPassPhraseCacheTtl < 15) {
- mPassPhraseCacheTtl = 15;
+
+ return START_STICKY;
+ }
+
+ /**
+ * Called when one specific passphrase for keyId timed out
+ *
+ * @param context
+ * @param keyId
+ */
+ private void timeout(Context context, long keyId) {
+ Log.d(Constants.TAG, "Timeout of " + keyId);
+
+ // remove passphrase corresponding to keyId from memory
+ mPassphraseCache.remove(keyId);
+
+ // stop whole service if no cached passphrases remaining
+ if (mPassphraseCache.isEmpty()) {
+ Log.d(Constants.TAG, "No passphrases remaining in memory, stopping service!");
+ stopSelf();
}
- mCacheHandler.removeCallbacks(mCacheTask);
- mCacheHandler.postDelayed(mCacheTask, 1000);
}
- static public boolean isRunning() {
- return mIsRunning;
+ @Override
+ public void onDestroy() {
+ Log.d(Constants.TAG, "PassphraseCacheService destroyed!");
+
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(mIntentReceiver);
}
- public class LocalBinder extends Binder {
- PassphraseCacheService getService() {
+ public class PassphraseCacheBinder extends Binder {
+ public PassphraseCacheService getService() {
return PassphraseCacheService.this;
}
}
+ private final IBinder mBinder = new PassphraseCacheBinder();
+
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
-}
+
+} \ No newline at end of file
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
index 40f2b3f43..b2463c5ac 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
@@ -25,6 +25,7 @@ import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.service.ApgService;
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.LookupUnknownKeyDialogFragment;
@@ -513,7 +514,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
// if we need a symmetric passphrase or a passphrase to use a secret key ask for it
if (getSecretKeyId() == Id.key.symmetric
- || PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) {
+ || PassphraseCacheService.getCachedPassphrase(this, getSecretKeyId()) == null) {
showPassphraseDialog();
} else {
if (mDecryptTarget == Id.target.file) {
@@ -548,7 +549,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
Messenger messenger = new Messenger(returnHandler);
try {
- PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
messenger, mSecretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java
index 4e5fda3db..831f33273 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java
@@ -30,6 +30,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.Preferences;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.service.ApgService;
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
@@ -659,7 +660,8 @@ public class EncryptActivity extends SherlockFragmentActivity {
return;
}
- if (getSecretKeyId() != 0 && PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) {
+ if (getSecretKeyId() != 0
+ && PassphraseCacheService.getCachedPassphrase(this, getSecretKeyId()) == null) {
showPassphraseDialog();
return;
@@ -697,7 +699,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
- messenger, mSecretKeyId);
+ EncryptActivity.this, messenger, mSecretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PGPMain.GeneralException e) {
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java
index 81a0545d1..b10667a40 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java
@@ -69,7 +69,8 @@ public class PreferencesActivity extends SherlockPreferenceActivity {
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
// restart cache service with new ttl
- PassphraseCacheService.startCacheService(PreferencesActivity.this);
+ // TODO: not needed anymore!
+ // PassphraseCacheService.startCacheService(PreferencesActivity.this);
return false;
}
});
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
index d7c272cf7..de799e2ac 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
@@ -21,6 +21,7 @@ import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
import org.thialfihar.android.apg.util.Log;
@@ -137,7 +138,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
public void checkPassPhraseAndEdit() {
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
- String passPhrase = PGPMain.getCachedPassPhrase(keyId);
+ String passPhrase = PassphraseCacheService.getCachedPassphrase(this, keyId);
if (passPhrase == null) {
showPassphraseDialog(keyId);
} else {
@@ -152,7 +153,8 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- String passPhrase = PGPMain.getCachedPassPhrase(secretKeyId);
+ String passPhrase = PassphraseCacheService.getCachedPassphrase(
+ SecretKeyListActivity.this, secretKeyId);
PGPMain.setEditPassPhrase(passPhrase);
editKey();
}
@@ -164,7 +166,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
- messenger, secretKeyId);
+ SecretKeyListActivity.this, messenger, secretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PGPMain.GeneralException e) {
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java
index 4c8c12bef..48c669aa0 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java
@@ -27,6 +27,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.Preferences;
import org.thialfihar.android.apg.service.ApgService;
import org.thialfihar.android.apg.service.ApgServiceHandler;
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
import com.actionbarsherlock.app.ActionBar;
@@ -141,7 +142,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
Messenger messenger = new Messenger(returnHandler);
try {
- PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
messenger, secretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
@@ -175,7 +176,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
/*
* get the user's passphrase for this key (if required)
*/
- String passphrase = PGPMain.getCachedPassPhrase(mMasterKeyId);
+ String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
if (passphrase == null) {
showPassphraseDialog(mMasterKeyId);
return; // bail out; need to wait until the user has entered the passphrase
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java
index 67d4e94c0..e8ef76e50 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java
@@ -31,6 +31,7 @@ import org.thialfihar.android.apg.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
@@ -38,13 +39,22 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
+
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.util.Log;
+
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
-public class PassphraseDialogFragment extends DialogFragment {
+public class PassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private Messenger mMessenger;
@@ -53,6 +63,8 @@ public class PassphraseDialogFragment extends DialogFragment {
public static final int MESSAGE_OKAY = 1;
+ private EditText mPassphraseEditText;
+
/**
* Creates new instance of this dialog fragment
*
@@ -63,11 +75,11 @@ public class PassphraseDialogFragment extends DialogFragment {
* @return
* @throws GeneralException
*/
- public static PassphraseDialogFragment newInstance(Messenger messenger, long secretKeyId)
- throws GeneralException {
+ public static PassphraseDialogFragment newInstance(Context context, Messenger messenger,
+ long secretKeyId) throws GeneralException {
// check if secret key has a passphrase
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
- if (!hasPassphrase(secretKeyId)) {
+ if (!hasPassphrase(context, secretKeyId)) {
throw new PGPMain.GeneralException("No passphrase! No passphrase dialog needed!");
}
}
@@ -88,7 +100,7 @@ public class PassphraseDialogFragment extends DialogFragment {
* @param secretKeyId
* @return true if it has a passphrase
*/
- private static boolean hasPassphrase(long secretKeyId) {
+ private static boolean hasPassphrase(Context context, long secretKeyId) {
// check if the key has no passphrase
try {
PGPSecretKey secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
@@ -101,7 +113,7 @@ public class PassphraseDialogFragment extends DialogFragment {
Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
// cache empty passphrase
- PGPMain.setCachedPassPhrase(secretKey.getKeyID(), "");
+ PassphraseCacheService.addCachedPassphrase(context, secretKey.getKeyID(), "");
return false;
}
@@ -112,6 +124,11 @@ public class PassphraseDialogFragment extends DialogFragment {
return true;
}
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
/**
* Creates dialog
*/
@@ -154,13 +171,13 @@ public class PassphraseDialogFragment extends DialogFragment {
View view = inflater.inflate(R.layout.passphrase, null);
alert.setView(view);
- final EditText input = (EditText) view.findViewById(R.id.passphrase_passphrase);
+ mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
- String passPhrase = input.getText().toString();
+ String passPhrase = mPassphraseEditText.getText().toString();
long keyId;
if (secretKey != null) {
try {
@@ -185,7 +202,7 @@ public class PassphraseDialogFragment extends DialogFragment {
// cache the new passphrase
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
- PGPMain.setCachedPassPhrase(keyId, passPhrase);
+ PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
sendMessageToHandler(MESSAGE_OKAY);
}
@@ -200,6 +217,32 @@ public class PassphraseDialogFragment extends DialogFragment {
return alert.create();
}
+ @Override
+ public void onActivityCreated(Bundle arg0) {
+ super.onActivityCreated(arg0);
+
+ // request focus and open soft keyboard
+ mPassphraseEditText.requestFocus();
+ getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
+ mPassphraseEditText.setOnEditorActionListener(this);
+ }
+
+ /**
+ * Associate the "done" button on the soft keyboard with the okay button in the view
+ */
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (EditorInfo.IME_ACTION_DONE == actionId) {
+ AlertDialog dialog = ((AlertDialog) getDialog());
+ Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ bt.performClick();
+ return true;
+ }
+ return false;
+ }
+
/**
* Send message back to handler which is initialized in a activity
*
@@ -218,4 +261,5 @@ public class PassphraseDialogFragment extends DialogFragment {
Log.w(Constants.TAG, "Messenger is null!", e);
}
}
+
} \ No newline at end of file
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/SetPassphraseDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/SetPassphraseDialogFragment.java
index 849f3428b..b23101a0a 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/dialog/SetPassphraseDialogFragment.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/SetPassphraseDialogFragment.java
@@ -29,12 +29,19 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
import org.thialfihar.android.apg.util.Log;
+
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
import android.widget.EditText;
+import android.widget.TextView;
import android.widget.Toast;
+import android.widget.TextView.OnEditorActionListener;
-public class SetPassphraseDialogFragment extends DialogFragment {
+public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private Messenger mMessenger;
private static final String ARG_MESSENGER = "messenger";
@@ -44,6 +51,9 @@ public class SetPassphraseDialogFragment extends DialogFragment {
public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase";
+ private EditText mPassphraseEditText;
+ private EditText mPassphraseAgainEditText;
+
/**
* Creates new instance of this dialog fragment
*
@@ -81,17 +91,17 @@ public class SetPassphraseDialogFragment extends DialogFragment {
LayoutInflater inflater = activity.getLayoutInflater();
View view = inflater.inflate(R.layout.passphrase_repeat, null);
- final EditText input1 = (EditText) view.findViewById(R.id.passphrase_passphrase);
- final EditText input2 = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
-
alert.setView(view);
+ mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
+ mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
+
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
- String passPhrase1 = input1.getText().toString();
- String passPhrase2 = input2.getText().toString();
+ String passPhrase1 = mPassphraseEditText.getText().toString();
+ String passPhrase2 = mPassphraseAgainEditText.getText().toString();
if (!passPhrase1.equals(passPhrase2)) {
Toast.makeText(
activity,
@@ -127,6 +137,32 @@ public class SetPassphraseDialogFragment extends DialogFragment {
return alert.create();
}
+ @Override
+ public void onActivityCreated(Bundle arg0) {
+ super.onActivityCreated(arg0);
+
+ // request focus and open soft keyboard
+ mPassphraseEditText.requestFocus();
+ getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
+ mPassphraseAgainEditText.setOnEditorActionListener(this);
+ }
+
+ /**
+ * Associate the "done" button on the soft keyboard with the okay button in the view
+ */
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (EditorInfo.IME_ACTION_DONE == actionId) {
+ AlertDialog dialog = ((AlertDialog) getDialog());
+ Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ bt.performClick();
+ return true;
+ }
+ return false;
+ }
+
/**
* Send message back to handler which is initialized in a activity
*
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java
index 140ba3a4f..f14dedbfc 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java
@@ -23,6 +23,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.PGPConversionHelper;
import org.thialfihar.android.apg.service.ApgServiceHandler;
import org.thialfihar.android.apg.service.ApgService;
+import org.thialfihar.android.apg.service.PassphraseCacheService;
import org.thialfihar.android.apg.ui.dialog.ProgressDialogFragment;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.util.Choice;
@@ -259,7 +260,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
String passPhrase;
if (mEditors.getChildCount() > 0) {
PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
- passPhrase = PGPMain.getCachedPassPhrase(masterKey.getKeyID());
+ passPhrase = PassphraseCacheService
+ .getCachedPassphrase(mActivity, masterKey.getKeyID());
data.putByteArray(ApgService.MASTER_KEY,
PGPConversionHelper.PGPSecretKeyToBytes(masterKey));
diff --git a/org_apg/src/org/thialfihar/android/apg/util/KeyServer.java b/org_apg/src/org/thialfihar/android/apg/util/KeyServer.java
index 5faa5a3df..97c6c7636 100644
--- a/org_apg/src/org/thialfihar/android/apg/util/KeyServer.java
+++ b/org_apg/src/org/thialfihar/android/apg/util/KeyServer.java
@@ -20,7 +20,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.Vector;
import android.os.Parcel;
import android.os.Parcelable;