mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
password cache introduced, not cleared yet.
This commit is contained in:
parent
cab78bf4c1
commit
363dcb62b8
@ -155,7 +155,8 @@ public class Apg {
|
|||||||
PublicKeys.KEY_DATA,
|
PublicKeys.KEY_DATA,
|
||||||
PublicKeys.WHO_ID, };
|
PublicKeys.WHO_ID, };
|
||||||
|
|
||||||
private static String mPassPhrase = null;
|
private static HashMap<Long, CachedPassPhrase> mPassPhraseCache =
|
||||||
|
new HashMap<Long, CachedPassPhrase>();
|
||||||
|
|
||||||
public static class GeneralException extends Exception {
|
public static class GeneralException extends Exception {
|
||||||
static final long serialVersionUID = 0xf812773342L;
|
static final long serialVersionUID = 0xf812773342L;
|
||||||
@ -271,12 +272,28 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setPassPhrase(String passPhrase) {
|
public static void setCachedPassPhrase(long keyId, String passPhrase) {
|
||||||
mPassPhrase = passPhrase;
|
mPassPhraseCache.put(keyId, new CachedPassPhrase(new Date().getTime(), passPhrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPassPhrase() {
|
public static String getCachedPassPhrase(long keyId) {
|
||||||
return mPassPhrase;
|
long realId = keyId;
|
||||||
|
if (realId != Id.key.symmetric) {
|
||||||
|
PGPSecretKeyRing keyRing = findSecretKeyRing(keyId);
|
||||||
|
if (keyRing == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PGPSecretKey masterKey = getMasterKey(keyRing);
|
||||||
|
if (masterKey == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
realId = masterKey.getKeyID();
|
||||||
|
}
|
||||||
|
CachedPassPhrase cpp = mPassPhraseCache.get(realId);
|
||||||
|
if (cpp == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return cpp.passPhrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPSecretKey createKey(Context context,
|
public static PGPSecretKey createKey(Context context,
|
||||||
@ -1440,7 +1457,7 @@ public class Apg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (secretKey == null) {
|
if (secretKey == null) {
|
||||||
return 0;
|
return Id.key.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
return secretKey.getKeyID();
|
return secretKey.getKeyID();
|
||||||
|
@ -32,7 +32,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
public class AskForSecretKeyPassPhrase {
|
public class AskForSecretKeyPassPhrase {
|
||||||
public static interface PassPhraseCallbackInterface {
|
public static interface PassPhraseCallbackInterface {
|
||||||
void passPhraseCallback(String passPhrase);
|
void passPhraseCallback(long keyId, String passPhrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dialog createDialog(Activity context, long secretKeyId,
|
public static Dialog createDialog(Activity context, long secretKeyId,
|
||||||
@ -43,7 +43,7 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
|
|
||||||
final PGPSecretKey secretKey;
|
final PGPSecretKey secretKey;
|
||||||
|
|
||||||
if (secretKeyId == 0) {
|
if (secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none) {
|
||||||
secretKey = null;
|
secretKey = null;
|
||||||
alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption));
|
alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption));
|
||||||
} else {
|
} else {
|
||||||
@ -71,6 +71,7 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
activity.removeDialog(Id.dialog.pass_phrase);
|
||||||
String passPhrase = "" + input.getText();
|
String passPhrase = "" + input.getText();
|
||||||
|
long keyId;
|
||||||
if (secretKey != null) {
|
if (secretKey != null) {
|
||||||
try {
|
try {
|
||||||
secretKey.extractPrivateKey(passPhrase.toCharArray(),
|
secretKey.extractPrivateKey(passPhrase.toCharArray(),
|
||||||
@ -81,8 +82,11 @@ public class AskForSecretKeyPassPhrase {
|
|||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
keyId = secretKey.getKeyID();
|
||||||
|
} else {
|
||||||
|
keyId = Id.key.symmetric;
|
||||||
}
|
}
|
||||||
cb.passPhraseCallback(passPhrase);
|
cb.passPhraseCallback(keyId, passPhrase);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -192,14 +192,9 @@ public class BaseActivity extends Activity
|
|||||||
case Id.request.secret_keys: {
|
case Id.request.secret_keys: {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Bundle bundle = data.getExtras();
|
Bundle bundle = data.getExtras();
|
||||||
long newId = bundle.getLong("selectedKeyId");
|
setSecretKeyId(bundle.getLong("selectedKeyId"));
|
||||||
if (getSecretKeyId() != newId) {
|
|
||||||
Apg.setPassPhrase(null);
|
|
||||||
}
|
|
||||||
setSecretKeyId(newId);
|
|
||||||
} else {
|
} else {
|
||||||
setSecretKeyId(0);
|
setSecretKeyId(Id.key.none);
|
||||||
Apg.setPassPhrase(null);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -271,8 +266,8 @@ public class BaseActivity extends Activity
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void passPhraseCallback(String passPhrase) {
|
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||||
Apg.setPassPhrase(passPhrase);
|
Apg.setCachedPassPhrase(keyId, passPhrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(Message msg) {
|
public void sendMessage(Message msg) {
|
||||||
|
39
src/org/thialfihar/android/apg/CachedPassPhrase.java
Normal file
39
src/org/thialfihar/android/apg/CachedPassPhrase.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package org.thialfihar.android.apg;
|
||||||
|
|
||||||
|
public class CachedPassPhrase {
|
||||||
|
public final long timestamp;
|
||||||
|
public final String passPhrase;
|
||||||
|
|
||||||
|
public CachedPassPhrase(long timestamp, String passPhrase) {
|
||||||
|
super();
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.passPhrase = passPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (!(other instanceof CachedPassPhrase)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedPassPhrase o = (CachedPassPhrase) other;
|
||||||
|
if (timestamp != o.timestamp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passPhrase != o.passPhrase) {
|
||||||
|
if (passPhrase == null || o.passPhrase == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passPhrase.equals(o.passPhrase)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "(" + timestamp + ", *******)";
|
||||||
|
}
|
||||||
|
}
|
@ -351,26 +351,35 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
setSecretKeyId(Apg.getDecryptionKeyId(this, in));
|
setSecretKeyId(Apg.getDecryptionKeyId(this, in));
|
||||||
if (getSecretKeyId() == 0) {
|
if (getSecretKeyId() == Id.key.none) {
|
||||||
throw new Apg.GeneralException(getString(R.string.error_noSecretKeyFound));
|
throw new Apg.GeneralException(getString(R.string.error_noSecretKeyFound));
|
||||||
}
|
}
|
||||||
mAssumeSymmetricEncryption = false;
|
mAssumeSymmetricEncryption = false;
|
||||||
} catch (Apg.NoAsymmetricEncryptionException e) {
|
} catch (Apg.NoAsymmetricEncryptionException e) {
|
||||||
setSecretKeyId(0);
|
setSecretKeyId(Id.key.symmetric);
|
||||||
// reopen the file/message to check whether there's
|
// look at the file/message again to check whether there's
|
||||||
// symmetric encryption data in there
|
// symmetric encryption data in there
|
||||||
if (mDecryptTarget == Id.target.file) {
|
if (mDecryptTarget == Id.target.file) {
|
||||||
in = new FileInputStream(mInputFilename);
|
((FileInputStream) in).reset();
|
||||||
} else {
|
} else {
|
||||||
in = new ByteArrayInputStream(mMessage.getText().toString().getBytes());
|
((ByteArrayInputStream) in).reset();
|
||||||
}
|
}
|
||||||
if (!Apg.hasSymmetricEncryption(this, in)) {
|
if (!Apg.hasSymmetricEncryption(this, in)) {
|
||||||
throw new Apg.GeneralException(getString(R.string.error_noKnownEncryptionFound));
|
throw new Apg.GeneralException(getString(R.string.error_noKnownEncryptionFound));
|
||||||
}
|
}
|
||||||
mAssumeSymmetricEncryption = true;
|
mAssumeSymmetricEncryption = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
showDialog(Id.dialog.pass_phrase);
|
if (getSecretKeyId() == Id.key.symmetric ||
|
||||||
|
Apg.getCachedPassPhrase(getSecretKeyId()) == null) {
|
||||||
|
showDialog(Id.dialog.pass_phrase);
|
||||||
|
} else {
|
||||||
|
if (mDecryptTarget == Id.target.file) {
|
||||||
|
askForOutputFilename();
|
||||||
|
} else {
|
||||||
|
decryptStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
error = getString(R.string.error_fileNotFound);
|
error = getString(R.string.error_fileNotFound);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -404,8 +413,8 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void passPhraseCallback(String passPhrase) {
|
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||||
super.passPhraseCallback(passPhrase);
|
super.passPhraseCallback(keyId, passPhrase);
|
||||||
if (mDecryptTarget == Id.target.file) {
|
if (mDecryptTarget == Id.target.file) {
|
||||||
askForOutputFilename();
|
askForOutputFilename();
|
||||||
} else {
|
} else {
|
||||||
@ -441,7 +450,7 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
if (mSignedOnly) {
|
if (mSignedOnly) {
|
||||||
data = Apg.verifyText(this, in, out, this);
|
data = Apg.verifyText(this, in, out, this);
|
||||||
} else {
|
} else {
|
||||||
data = Apg.decrypt(this, in, out, Apg.getPassPhrase(),
|
data = Apg.decrypt(this, in, out, Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||||
this, mAssumeSymmetricEncryption);
|
this, mAssumeSymmetricEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import java.util.Vector;
|
|||||||
import org.bouncycastle2.openpgp.PGPException;
|
import org.bouncycastle2.openpgp.PGPException;
|
||||||
import org.bouncycastle2.openpgp.PGPSecretKey;
|
import org.bouncycastle2.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle2.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle2.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.thialfihar.android.apg.ui.widget.KeyEditor;
|
||||||
import org.thialfihar.android.apg.ui.widget.SectionView;
|
import org.thialfihar.android.apg.ui.widget.SectionView;
|
||||||
import org.thialfihar.android.apg.utils.IterableIterator;
|
import org.thialfihar.android.apg.utils.IterableIterator;
|
||||||
|
|
||||||
@ -70,9 +71,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
keyId = intent.getExtras().getLong("keyId");
|
keyId = intent.getExtras().getLong("keyId");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyId == 0) {
|
if (keyId != 0) {
|
||||||
Apg.setPassPhrase(null);
|
|
||||||
} else {
|
|
||||||
PGPSecretKey masterKey = null;
|
PGPSecretKey masterKey = null;
|
||||||
mKeyRing = Apg.getSecretKeyRing(keyId);
|
mKeyRing = Apg.getSecretKeyRing(keyId);
|
||||||
if (mKeyRing != null) {
|
if (mKeyRing != null) {
|
||||||
@ -88,10 +87,6 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Apg.getPassPhrase() == null) {
|
|
||||||
Apg.setPassPhrase("");
|
|
||||||
}
|
|
||||||
|
|
||||||
mSaveButton = (Button) findViewById(R.id.btn_save);
|
mSaveButton = (Button) findViewById(R.id.btn_save);
|
||||||
mDiscardButton = (Button) findViewById(R.id.btn_discard);
|
mDiscardButton = (Button) findViewById(R.id.btn_discard);
|
||||||
|
|
||||||
@ -114,15 +109,26 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
Toast.makeText(this, "Warning: Key editing is still kind of beta.", Toast.LENGTH_LONG).show();
|
Toast.makeText(this, "Warning: Key editing is still kind of beta.", Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMasterKeyId() {
|
||||||
|
if (mKeys.getEditors().getChildCount() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ((KeyEditor) mKeys.getEditors().getChildAt(0)).getValue().getKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean havePassPhrase() {
|
public boolean havePassPhrase() {
|
||||||
return (Apg.getPassPhrase() != null && !Apg.getPassPhrase().equals("")) ||
|
long keyId = getMasterKeyId();
|
||||||
|
if (keyId == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (Apg.getCachedPassPhrase(keyId) != null && !Apg.getCachedPassPhrase(keyId).equals("")) ||
|
||||||
(mNewPassPhrase != null && !mNewPassPhrase.equals(""));
|
(mNewPassPhrase != null && !mNewPassPhrase.equals(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
menu.add(0, Id.menu.option.new_pass_phrase, 0,
|
menu.add(0, Id.menu.option.new_pass_phrase, 0,
|
||||||
(havePassPhrase() ? R.string.menu_changePassPhrase : R.string.menu_setPassPhrase))
|
(havePassPhrase() ? R.string.menu_changePassPhrase : R.string.menu_setCachedPassPhrase))
|
||||||
.setIcon(android.R.drawable.ic_menu_add);
|
.setIcon(android.R.drawable.ic_menu_add);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -151,7 +157,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
if (havePassPhrase()) {
|
if (havePassPhrase()) {
|
||||||
alert.setTitle(R.string.title_changePassPhrase);
|
alert.setTitle(R.string.title_changePassPhrase);
|
||||||
} else {
|
} else {
|
||||||
alert.setTitle(R.string.title_setPassPhrase);
|
alert.setTitle(R.string.title_setCachedPassPhrase);
|
||||||
}
|
}
|
||||||
alert.setMessage(R.string.enterPassPhraseTwice);
|
alert.setMessage(R.string.enterPassPhraseTwice);
|
||||||
|
|
||||||
@ -227,7 +233,7 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
|
|||||||
Message msg = new Message();
|
Message msg = new Message();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String oldPassPhrase = Apg.getPassPhrase();
|
String oldPassPhrase = Apg.getCachedPassPhrase(getMasterKeyId());
|
||||||
String newPassPhrase = mNewPassPhrase;
|
String newPassPhrase = mNewPassPhrase;
|
||||||
if (newPassPhrase == null) {
|
if (newPassPhrase == null) {
|
||||||
newPassPhrase = oldPassPhrase;
|
newPassPhrase = oldPassPhrase;
|
||||||
|
@ -235,8 +235,7 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
if (checkBox.isChecked()) {
|
if (checkBox.isChecked()) {
|
||||||
selectSecretKey();
|
selectSecretKey();
|
||||||
} else {
|
} else {
|
||||||
setSecretKeyId(0);
|
setSecretKeyId(Id.key.none);
|
||||||
Apg.setPassPhrase(null);
|
|
||||||
updateView();
|
updateView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +446,7 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSecretKeyId() != 0 && Apg.getPassPhrase() == null) {
|
if (getSecretKeyId() != 0 && Apg.getCachedPassPhrase(getSecretKeyId()) == null) {
|
||||||
showDialog(Id.dialog.pass_phrase);
|
showDialog(Id.dialog.pass_phrase);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -465,8 +464,8 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void passPhraseCallback(String passPhrase) {
|
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||||
super.passPhraseCallback(passPhrase);
|
super.passPhraseCallback(keyId, passPhrase);
|
||||||
if (mEncryptTarget == Id.target.file) {
|
if (mEncryptTarget == Id.target.file) {
|
||||||
askForOutputFilename();
|
askForOutputFilename();
|
||||||
} else {
|
} else {
|
||||||
@ -544,11 +543,12 @@ public class EncryptActivity extends BaseActivity {
|
|||||||
|
|
||||||
if (signOnly) {
|
if (signOnly) {
|
||||||
Apg.signText(this, in, out, getSecretKeyId(),
|
Apg.signText(this, in, out, getSecretKeyId(),
|
||||||
Apg.getPassPhrase(), getDefaultHashAlgorithm(), this);
|
Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||||
|
getDefaultHashAlgorithm(), this);
|
||||||
} else {
|
} else {
|
||||||
Apg.encrypt(this, in, out, size, useAsciiArmour,
|
Apg.encrypt(this, in, out, size, useAsciiArmour,
|
||||||
encryptionKeyIds, signatureKeyId,
|
encryptionKeyIds, signatureKeyId,
|
||||||
Apg.getPassPhrase(), this,
|
Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||||
getDefaultEncryptionAlgorithm(), getDefaultHashAlgorithm(),
|
getDefaultEncryptionAlgorithm(), getDefaultHashAlgorithm(),
|
||||||
passPhrase);
|
passPhrase);
|
||||||
}
|
}
|
||||||
|
@ -112,4 +112,9 @@ public final class Id {
|
|||||||
public static final int file = 0x21070003;
|
public static final int file = 0x21070003;
|
||||||
public static final int message = 0x21070004;
|
public static final int message = 0x21070004;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class key {
|
||||||
|
public static final int none = 0;
|
||||||
|
public static final int symmetric = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,8 +264,8 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void passPhraseCallback(String passPhrase) {
|
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||||
super.passPhraseCallback(passPhrase);
|
super.passPhraseCallback(keyId, passPhrase);
|
||||||
editKey();
|
editKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,12 +298,17 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
String error = null;
|
String error = null;
|
||||||
try {
|
try {
|
||||||
PGPSecretKey masterKey = null;
|
PGPSecretKey masterKey = null;
|
||||||
|
String passPhrase;
|
||||||
if (mEditors.getChildCount() > 0) {
|
if (mEditors.getChildCount() > 0) {
|
||||||
masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
|
masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
|
||||||
|
passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID());
|
||||||
|
} else {
|
||||||
|
passPhrase = "";
|
||||||
}
|
}
|
||||||
mNewKey = Apg.createKey(getContext(),
|
mNewKey = Apg.createKey(getContext(),
|
||||||
mNewKeyAlgorithmChoice.getId(),
|
mNewKeyAlgorithmChoice.getId(),
|
||||||
mNewKeySize, Apg.getPassPhrase(), masterKey);
|
mNewKeySize, passPhrase,
|
||||||
|
masterKey);
|
||||||
} catch (NoSuchProviderException e) {
|
} catch (NoSuchProviderException e) {
|
||||||
error = e.getMessage();
|
error = e.getMessage();
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user