add AndroidPassphraseCacheInterface abstraction
This commit is contained in:
parent
83f5f557f0
commit
0987c18d8b
|
@ -0,0 +1,47 @@
|
|||
package org.sufficientlysecure.keychain.operations;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants.key;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
|
||||
public class AndroidPassphraseCacheInterface implements PassphraseCacheInterface {
|
||||
public static AndroidPassphraseCacheInterface getInstance(Context context) {
|
||||
KeyRepository keyRepository = KeyRepository.create(context);
|
||||
return new AndroidPassphraseCacheInterface(context, keyRepository);
|
||||
}
|
||||
|
||||
private Context context;
|
||||
private KeyRepository keyRepository;
|
||||
|
||||
private AndroidPassphraseCacheInterface(Context context, KeyRepository keyRepository) {
|
||||
this.context = context;
|
||||
this.keyRepository = keyRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long subKeyId) {
|
||||
if (subKeyId != key.symmetric) {
|
||||
Long masterKeyId = keyRepository.getMasterKeyIdBySubkeyId(subKeyId);
|
||||
if (masterKeyId == null) {
|
||||
return null;
|
||||
}
|
||||
return getCachedPassphrase(masterKeyId, subKeyId);
|
||||
}
|
||||
return getCachedPassphrase(key.symmetric, key.symmetric);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) {
|
||||
try {
|
||||
return PassphraseCacheService.getCachedPassphrase(context, masterKeyId, subKeyId);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,22 +25,20 @@ import android.os.Parcelable;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants.key;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public abstract class BaseOperation<T extends Parcelable> implements PassphraseCacheInterface {
|
||||
|
||||
public abstract class BaseOperation<T extends Parcelable> {
|
||||
|
||||
final public Context mContext;
|
||||
final public Progressable mProgressable;
|
||||
final public AtomicBoolean mCancelled;
|
||||
|
||||
final public KeyRepository mKeyRepository;
|
||||
final public AndroidPassphraseCacheInterface passphraseCacheInterface;
|
||||
|
||||
/** An abstract base class for all *Operation classes. It provides a number
|
||||
* of common methods for progress, cancellation and passphrase cache handling.
|
||||
|
@ -68,6 +66,7 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
|
|||
this.mContext = context;
|
||||
this.mProgressable = progressable;
|
||||
this.mKeyRepository = keyRepository;
|
||||
this.passphraseCacheInterface = AndroidPassphraseCacheInterface.getInstance(context);
|
||||
mCancelled = null;
|
||||
}
|
||||
|
||||
|
@ -76,6 +75,7 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
|
|||
mContext = context;
|
||||
mProgressable = progressable;
|
||||
mKeyRepository = keyRepository;
|
||||
passphraseCacheInterface = AndroidPassphraseCacheInterface.getInstance(context);
|
||||
mCancelled = cancelled;
|
||||
}
|
||||
|
||||
|
@ -103,27 +103,4 @@ public abstract class BaseOperation<T extends Parcelable> implements PassphraseC
|
|||
mProgressable.setPreventCancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
|
||||
if (subKeyId != key.symmetric) {
|
||||
Long masterKeyId = mKeyRepository.getMasterKeyIdBySubkeyId(subKeyId);
|
||||
if (masterKeyId == null) {
|
||||
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||
}
|
||||
return getCachedPassphrase(masterKeyId, subKeyId);
|
||||
}
|
||||
return getCachedPassphrase(key.symmetric, key.symmetric);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
|
||||
try {
|
||||
return PassphraseCacheService.getCachedPassphrase(
|
||||
mContext, masterKeyId, subKeyId);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.sufficientlysecure.keychain.operations.results.UploadResult;
|
|||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
|
@ -89,11 +88,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
|||
case PASSPHRASE:
|
||||
passphrase = cryptoInput.getPassphrase();
|
||||
if (passphrase == null) {
|
||||
try {
|
||||
passphrase = getCachedPassphrase(masterKeyId, masterKeyId);
|
||||
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
|
||||
// treat as a cache miss for error handling purposes
|
||||
}
|
||||
passphrase = passphraseCacheInterface.getCachedPassphrase(masterKeyId, masterKeyId);
|
||||
}
|
||||
|
||||
if (passphrase == null) {
|
||||
|
|
|
@ -20,13 +20,6 @@ package org.sufficientlysecure.keychain.pgp;
|
|||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public interface PassphraseCacheInterface {
|
||||
class NoSecretKeyException extends Exception {
|
||||
public NoSecretKeyException() {
|
||||
}
|
||||
}
|
||||
|
||||
Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
|
||||
|
||||
Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
|
||||
|
||||
Passphrase getCachedPassphrase(long subKeyId);
|
||||
Passphrase getCachedPassphrase(long masterKeyId, long subKeyId);
|
||||
}
|
||||
|
|
|
@ -679,18 +679,11 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||
} else if (cryptoInput.hasPassphraseForSubkey(subKeyId)) {
|
||||
passphrase = cryptoInput.getPassphrase();
|
||||
} else {
|
||||
// if no passphrase was explicitly set try to get it from the cache service
|
||||
try {
|
||||
// returns "" if key has no passphrase
|
||||
passphrase = getCachedPassphrase(subKeyId);
|
||||
// returns "" if key has no passphrase
|
||||
passphrase = passphraseCacheInterface.getCachedPassphrase(subKeyId);
|
||||
if (passphrase != null) {
|
||||
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
|
||||
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
|
||||
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
|
||||
return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
|
||||
}
|
||||
|
||||
// if passphrase was not cached, return here indicating that a passphrase is missing!
|
||||
if (passphrase == null) {
|
||||
} else {
|
||||
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
|
||||
requirePassphraseBuilder.add(masterKeyId, subKeyId);
|
||||
continue;
|
||||
|
@ -741,14 +734,10 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||
// indicating that a passphrase is missing!
|
||||
if (!cryptoInput.hasPassphraseForSymmetric()) {
|
||||
|
||||
try {
|
||||
passphrase = getCachedPassphrase(key.symmetric);
|
||||
passphrase = passphraseCacheInterface.getCachedPassphrase(key.symmetric);
|
||||
if (passphrase != null) {
|
||||
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
|
||||
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
|
||||
// nvm
|
||||
}
|
||||
|
||||
if (passphrase == null) {
|
||||
} else {
|
||||
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
|
||||
RequiredInputParcel requiredInputParcel = customRequiredInputParcel != null ?
|
||||
customRequiredInputParcel : RequiredInputParcel.createRequiredSymmetricPassphrase();
|
||||
|
|
|
@ -270,10 +270,8 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
|||
case PASSPHRASE: {
|
||||
Passphrase localPassphrase = cryptoInput.getPassphrase();
|
||||
if (localPassphrase == null) {
|
||||
try {
|
||||
localPassphrase = getCachedPassphrase(signingMasterKeyId, signingKey.getKeyId());
|
||||
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
|
||||
}
|
||||
localPassphrase = passphraseCacheInterface.getCachedPassphrase(
|
||||
signingMasterKeyId, signingKey.getKeyId());
|
||||
}
|
||||
if (localPassphrase == null) {
|
||||
log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1);
|
||||
|
|
|
@ -26,15 +26,14 @@ import android.support.annotation.NonNull;
|
|||
import org.bouncycastle.openpgp.AuthenticationSignatureGenerator;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.operations.BaseOperation;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
@ -172,10 +171,7 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
|
|||
case PASSPHRASE: {
|
||||
Passphrase localPassphrase = cryptoInput.getPassphrase();
|
||||
if (localPassphrase == null) {
|
||||
try {
|
||||
localPassphrase = getCachedPassphrase(authMasterKeyId, authKey.getKeyId());
|
||||
} catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
|
||||
}
|
||||
localPassphrase = passphraseCacheInterface.getCachedPassphrase(authMasterKeyId, authKey.getKeyId());
|
||||
}
|
||||
if (localPassphrase == null) {
|
||||
log.add(LogType.MSG_AUTH_PENDING_PASSPHRASE, indent + 1);
|
||||
|
|
|
@ -1084,9 +1084,7 @@ public class PgpEncryptDecryptTest {
|
|||
|
||||
return new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
|
||||
KeyWritableRepository.create(RuntimeEnvironment.application), null) {
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
|
||||
throws NoSecretKeyException {
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) {
|
||||
if (checkMasterKeyId != null) {
|
||||
Assert.assertEquals("requested passphrase should be for expected master key id",
|
||||
(long) checkMasterKeyId, masterKeyId);
|
||||
|
|
Loading…
Reference in New Issue