honour the pass phrase cache TTL by running a timer and removing expired cached pass phrases

This commit is contained in:
Thialfihar 2010-05-16 13:17:45 +00:00
parent f94af3e4e6
commit 9855f4d144
4 changed files with 55 additions and 9 deletions

View file

@ -41,6 +41,7 @@ import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Vector; import java.util.Vector;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -293,9 +294,26 @@ public class Apg {
if (cpp == null) { if (cpp == null) {
return null; return null;
} }
// set it again to reset the cache life cycle
setCachedPassPhrase(realId, cpp.passPhrase);
return cpp.passPhrase; return cpp.passPhrase;
} }
public static void cleanUpCache(int ttl) {
long now = new Date().getTime();
Vector<Long> oldKeys = new Vector<Long>();
for (Map.Entry<Long, CachedPassPhrase> 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, public static PGPSecretKey createKey(Context context,
int algorithmChoice, int keySize, String passPhrase, int algorithmChoice, int keySize, String passPhrase,
PGPSecretKey masterKey) PGPSecretKey masterKey)
@ -1266,7 +1284,7 @@ public class Apg {
PGPSignatureGenerator signatureGenerator = null; PGPSignatureGenerator signatureGenerator = null;
progress.setProgress(R.string.progress_preparingStreams, 5, 100); progress.setProgress(R.string.progress_preparingStreams, 5, 100);
// encryptFile and compress input file content // encrypt and compress input file content
PGPEncryptedDataGenerator cPk = PGPEncryptedDataGenerator cPk =
new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(), new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(),
new BouncyCastleProvider()); new BouncyCastleProvider());

View file

@ -17,6 +17,8 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.File; import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
import org.bouncycastle2.bcpg.HashAlgorithmTags; import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData; import org.bouncycastle2.openpgp.PGPEncryptedData;
@ -50,6 +52,8 @@ public class BaseActivity extends Activity
private String mDeleteFile = null; private String mDeleteFile = null;
protected static SharedPreferences mPreferences = null; protected static SharedPreferences mPreferences = null;
private static Timer mCacheTimer = new Timer();
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
@ -65,6 +69,29 @@ public class BaseActivity extends Activity
mPreferences = getPreferences(MODE_PRIVATE); mPreferences = getPreferences(MODE_PRIVATE);
} }
Apg.initialize(this); 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 @Override
@ -98,7 +125,6 @@ public class BaseActivity extends Activity
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
// in case it is a progress dialog // in case it is a progress dialog
mProgressDialog = new ProgressDialog(this); mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
@ -354,14 +380,16 @@ public class BaseActivity extends Activity
return mSecretKeyId; return mSecretKeyId;
} }
public int getPassPhraseCache() { public int getPassPhraseCacheTtl() {
return mPreferences.getInt(Constants.pref.pass_phrase_cache_length, 300); 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(); 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(); editor.commit();
setPassPhraseCacheTimer();
} }
public int getDefaultEncryptionAlgorithm() { public int getDefaultEncryptionAlgorithm() {

View file

@ -28,6 +28,6 @@ public final class Constants {
public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm"; public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm";
public static final String default_hash_algorithm = "defaultHashAlgorithm"; public static final String default_hash_algorithm = "defaultHashAlgorithm";
public static final String default_ascii_armour = "defaultAsciiArmour"; 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";
} }
} }

View file

@ -55,7 +55,7 @@ public class PreferencesActivity extends BaseActivity {
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mPassPhraseCache.setAdapter(adapter); mPassPhraseCache.setAdapter(adapter);
int passPhraseCache = getPassPhraseCache(); int passPhraseCache = getPassPhraseCacheTtl();
for (int i = 0; i < choices.length; ++i) { for (int i = 0; i < choices.length; ++i) {
if (choices[i].getId() == passPhraseCache) { if (choices[i].getId() == passPhraseCache) {
mPassPhraseCache.setSelection(i); mPassPhraseCache.setSelection(i);
@ -66,7 +66,7 @@ public class PreferencesActivity extends BaseActivity {
mPassPhraseCache.setOnItemSelectedListener(new OnItemSelectedListener() { mPassPhraseCache.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> adapter, View view, int index, long id) { public void onItemSelected(AdapterView<?> adapter, View view, int index, long id) {
setPassPhraseCache(((Choice) mPassPhraseCache.getSelectedItem()).getId()); setPassPhraseCacheTtl(((Choice) mPassPhraseCache.getSelectedItem()).getId());
} }
@Override @Override