From 9855f4d1441ac1e5dc7df19ebd0272e5f94e2aa2 Mon Sep 17 00:00:00 2001 From: Thialfihar Date: Sun, 16 May 2010 13:17:45 +0000 Subject: [PATCH] honour the pass phrase cache TTL by running a timer and removing expired cached pass phrases --- src/org/thialfihar/android/apg/Apg.java | 20 +++++++++- .../thialfihar/android/apg/BaseActivity.java | 38 ++++++++++++++++--- src/org/thialfihar/android/apg/Constants.java | 2 +- .../android/apg/PreferencesActivity.java | 4 +- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index a453cdf4a..5071e3d01 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -41,6 +41,7 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.Vector; import java.util.regex.Pattern; @@ -293,9 +294,26 @@ public class Apg { if (cpp == null) { return null; } + // set it again to reset the cache life cycle + setCachedPassPhrase(realId, cpp.passPhrase); return cpp.passPhrase; } + public static void cleanUpCache(int ttl) { + long now = new Date().getTime(); + + Vector oldKeys = new Vector(); + for (Map.Entry pair : mPassPhraseCache.entrySet()) { + if ((now - pair.getValue().timestamp) >= 1000 * ttl) { + oldKeys.add(pair.getKey()); + } + } + + for (long keyId : oldKeys) { + mPassPhraseCache.remove(keyId); + } + } + public static PGPSecretKey createKey(Context context, int algorithmChoice, int keySize, String passPhrase, PGPSecretKey masterKey) @@ -1266,7 +1284,7 @@ public class Apg { PGPSignatureGenerator signatureGenerator = null; progress.setProgress(R.string.progress_preparingStreams, 5, 100); - // encryptFile and compress input file content + // encrypt and compress input file content PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(), new BouncyCastleProvider()); diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java index 70ddb7402..244c4aee6 100644 --- a/src/org/thialfihar/android/apg/BaseActivity.java +++ b/src/org/thialfihar/android/apg/BaseActivity.java @@ -17,6 +17,8 @@ package org.thialfihar.android.apg; import java.io.File; +import java.util.Timer; +import java.util.TimerTask; import org.bouncycastle2.bcpg.HashAlgorithmTags; import org.bouncycastle2.openpgp.PGPEncryptedData; @@ -50,6 +52,8 @@ public class BaseActivity extends Activity private String mDeleteFile = null; protected static SharedPreferences mPreferences = null; + private static Timer mCacheTimer = new Timer(); + private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -65,6 +69,29 @@ public class BaseActivity extends Activity mPreferences = getPreferences(MODE_PRIVATE); } Apg.initialize(this); + if (mCacheTimer == null) { + setPassPhraseCacheTimer(); + } + } + + private void setPassPhraseCacheTimer() { + if (mCacheTimer != null) { + mCacheTimer.cancel(); + mCacheTimer = null; + } + int ttl = getPassPhraseCacheTtl(); + if (ttl == 0) { + // no timer needed + return; + } + // 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 int the cache is 1.5 * ttl + mCacheTimer = new Timer(); + mCacheTimer.scheduleAtFixedRate(new TimerTask() { + public void run() { + Apg.cleanUpCache(BaseActivity.this.getPassPhraseCacheTtl()); + } + }, 0, ttl * 1000 / 2); } @Override @@ -98,7 +125,6 @@ public class BaseActivity extends Activity @Override protected Dialog onCreateDialog(int id) { - // in case it is a progress dialog mProgressDialog = new ProgressDialog(this); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); @@ -354,14 +380,16 @@ public class BaseActivity extends Activity return mSecretKeyId; } - public int getPassPhraseCache() { - return mPreferences.getInt(Constants.pref.pass_phrase_cache_length, 300); + public int getPassPhraseCacheTtl() { + return mPreferences.getInt(Constants.pref.pass_phrase_cache_ttl, 300); } - public void setPassPhraseCache(int value) { + public void setPassPhraseCacheTtl(int value) { SharedPreferences.Editor editor = mPreferences.edit(); - editor.putInt(Constants.pref.pass_phrase_cache_length, value); + editor.putInt(Constants.pref.pass_phrase_cache_ttl, value); editor.commit(); + + setPassPhraseCacheTimer(); } public int getDefaultEncryptionAlgorithm() { diff --git a/src/org/thialfihar/android/apg/Constants.java b/src/org/thialfihar/android/apg/Constants.java index 40a77645d..a880d3328 100644 --- a/src/org/thialfihar/android/apg/Constants.java +++ b/src/org/thialfihar/android/apg/Constants.java @@ -28,6 +28,6 @@ public final class Constants { public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm"; public static final String default_hash_algorithm = "defaultHashAlgorithm"; public static final String default_ascii_armour = "defaultAsciiArmour"; - public static final String pass_phrase_cache_length = "passPhraseCacheLength"; + public static final String pass_phrase_cache_ttl = "passPhraseCacheTtl"; } } diff --git a/src/org/thialfihar/android/apg/PreferencesActivity.java b/src/org/thialfihar/android/apg/PreferencesActivity.java index 8a1c02475..f6bc4c8b4 100644 --- a/src/org/thialfihar/android/apg/PreferencesActivity.java +++ b/src/org/thialfihar/android/apg/PreferencesActivity.java @@ -55,7 +55,7 @@ public class PreferencesActivity extends BaseActivity { adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mPassPhraseCache.setAdapter(adapter); - int passPhraseCache = getPassPhraseCache(); + int passPhraseCache = getPassPhraseCacheTtl(); for (int i = 0; i < choices.length; ++i) { if (choices[i].getId() == passPhraseCache) { mPassPhraseCache.setSelection(i); @@ -66,7 +66,7 @@ public class PreferencesActivity extends BaseActivity { mPassPhraseCache.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapter, View view, int index, long id) { - setPassPhraseCache(((Choice) mPassPhraseCache.getSelectedItem()).getId()); + setPassPhraseCacheTtl(((Choice) mPassPhraseCache.getSelectedItem()).getId()); } @Override