mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-17 07:30:14 -05:00
PgpDecryptVerify is now context-free
This commit is contained in:
parent
9b15482c41
commit
45b450e78a
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
@ -55,10 +54,8 @@ import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactory
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
|
||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||||
@ -78,8 +75,8 @@ import java.util.Set;
|
|||||||
* This class uses a Builder pattern!
|
* This class uses a Builder pattern!
|
||||||
*/
|
*/
|
||||||
public class PgpDecryptVerify {
|
public class PgpDecryptVerify {
|
||||||
private Context mContext;
|
|
||||||
private ProviderHelper mProviderHelper;
|
private ProviderHelper mProviderHelper;
|
||||||
|
private PassphraseCache mPassphraseCache;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
@ -90,8 +87,8 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
private PgpDecryptVerify(Builder builder) {
|
private PgpDecryptVerify(Builder builder) {
|
||||||
// private Constructor can only be called from Builder
|
// private Constructor can only be called from Builder
|
||||||
this.mContext = builder.mContext;
|
this.mProviderHelper = builder.mProviderHelper;
|
||||||
this.mProviderHelper = new ProviderHelper(mContext);
|
this.mPassphraseCache = builder.mPassphraseCache;
|
||||||
this.mData = builder.mData;
|
this.mData = builder.mData;
|
||||||
this.mOutStream = builder.mOutStream;
|
this.mOutStream = builder.mOutStream;
|
||||||
|
|
||||||
@ -103,7 +100,8 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
// mandatory parameter
|
// mandatory parameter
|
||||||
private Context mContext;
|
private ProviderHelper mProviderHelper;
|
||||||
|
private PassphraseCache mPassphraseCache;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
@ -113,8 +111,10 @@ public class PgpDecryptVerify {
|
|||||||
private String mPassphrase = null;
|
private String mPassphrase = null;
|
||||||
private Set<Long> mAllowedKeyIds = null;
|
private Set<Long> mAllowedKeyIds = null;
|
||||||
|
|
||||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
public Builder(ProviderHelper providerHelper, PassphraseCache passphraseCache,
|
||||||
this.mContext = context;
|
InputData data, OutputStream outStream) {
|
||||||
|
this.mProviderHelper = providerHelper;
|
||||||
|
this.mPassphraseCache = passphraseCache;
|
||||||
this.mData = data;
|
this.mData = data;
|
||||||
this.mOutStream = outStream;
|
this.mOutStream = outStream;
|
||||||
}
|
}
|
||||||
@ -163,6 +163,35 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface PassphraseCache {
|
||||||
|
public String getCachedPassphrase(long masterKeyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidDataException extends Exception {
|
||||||
|
public InvalidDataException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeyExtractionException extends Exception {
|
||||||
|
public KeyExtractionException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WrongPassphraseException extends Exception {
|
||||||
|
public WrongPassphraseException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NoSecretKeyException extends Exception {
|
||||||
|
public NoSecretKeyException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class IntegrityCheckFailedException extends Exception {
|
||||||
|
public IntegrityCheckFailedException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts and/or verifies data based on parameters of class
|
* Decrypts and/or verifies data based on parameters of class
|
||||||
*
|
*
|
||||||
@ -173,7 +202,9 @@ public class PgpDecryptVerify {
|
|||||||
* @throws SignatureException
|
* @throws SignatureException
|
||||||
*/
|
*/
|
||||||
public PgpDecryptVerifyResult execute()
|
public PgpDecryptVerifyResult execute()
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException,
|
||||||
|
WrongPassphraseException, NoSecretKeyException, KeyExtractionException,
|
||||||
|
InvalidDataException, IntegrityCheckFailedException {
|
||||||
// automatically works with ascii armor input and binary
|
// automatically works with ascii armor input and binary
|
||||||
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
|
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
|
||||||
if (in instanceof ArmoredInputStream) {
|
if (in instanceof ArmoredInputStream) {
|
||||||
@ -202,7 +233,9 @@ public class PgpDecryptVerify {
|
|||||||
* @throws SignatureException
|
* @throws SignatureException
|
||||||
*/
|
*/
|
||||||
private PgpDecryptVerifyResult decryptVerify(InputStream in)
|
private PgpDecryptVerifyResult decryptVerify(InputStream in)
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException,
|
||||||
|
WrongPassphraseException, KeyExtractionException, NoSecretKeyException,
|
||||||
|
InvalidDataException, IntegrityCheckFailedException {
|
||||||
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
||||||
|
|
||||||
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
||||||
@ -219,7 +252,8 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (enc == null) {
|
if (enc == null) {
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_invalid_data));
|
// throw new PgpGeneralException(mContext.getString(R.string.error_invalid_data));
|
||||||
|
throw new InvalidDataException();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream clear;
|
InputStream clear;
|
||||||
@ -287,8 +321,9 @@ public class PgpDecryptVerify {
|
|||||||
// if no passphrase was explicitly set try to get it from the cache service
|
// if no passphrase was explicitly set try to get it from the cache service
|
||||||
if (mPassphrase == null) {
|
if (mPassphrase == null) {
|
||||||
// returns "" if key has no passphrase
|
// returns "" if key has no passphrase
|
||||||
mPassphrase =
|
mPassphrase = mPassphraseCache.getCachedPassphrase(masterKeyId);
|
||||||
PassphraseCacheService.getCachedPassphrase(mContext, masterKeyId);
|
// mPassphrase =
|
||||||
|
// PassphraseCacheService.getCachedPassphrase(mContext, masterKeyId);
|
||||||
|
|
||||||
// if passphrase was not cached, return here
|
// if passphrase was not cached, return here
|
||||||
// indicating that a passphrase is missing!
|
// indicating that a passphrase is missing!
|
||||||
@ -347,11 +382,13 @@ public class PgpDecryptVerify {
|
|||||||
mPassphrase.toCharArray());
|
mPassphrase.toCharArray());
|
||||||
privateKey = secretKey.extractPrivateKey(keyDecryptor);
|
privateKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
throw new PGPException(mContext.getString(R.string.error_wrong_passphrase));
|
// throw new PGPException(mContext.getString(R.string.error_wrong_passphrase));
|
||||||
|
throw new WrongPassphraseException();
|
||||||
}
|
}
|
||||||
if (privateKey == null) {
|
if (privateKey == null) {
|
||||||
throw new PgpGeneralException(
|
// throw new PgpGeneralException(
|
||||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
// mContext.getString(R.string.error_could_not_extract_private_key));
|
||||||
|
throw new KeyExtractionException();
|
||||||
}
|
}
|
||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
|
||||||
@ -365,7 +402,8 @@ public class PgpDecryptVerify {
|
|||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
} else {
|
} else {
|
||||||
// no packet has been found where we have the corresponding secret key in our db
|
// no packet has been found where we have the corresponding secret key in our db
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
// throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
||||||
|
throw new NoSecretKeyException();
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
|
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
|
||||||
@ -515,7 +553,8 @@ public class PgpDecryptVerify {
|
|||||||
} else {
|
} else {
|
||||||
// failed
|
// failed
|
||||||
Log.d(Constants.TAG, "Integrity verification: failed!");
|
Log.d(Constants.TAG, "Integrity verification: failed!");
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_integrity_check_failed));
|
// throw new PgpGeneralException(mContext.getString(R.string.error_integrity_check_failed));
|
||||||
|
throw new IntegrityCheckFailedException();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no integrity check
|
// no integrity check
|
||||||
@ -543,7 +582,7 @@ public class PgpDecryptVerify {
|
|||||||
* @throws SignatureException
|
* @throws SignatureException
|
||||||
*/
|
*/
|
||||||
private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn)
|
private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn)
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException, InvalidDataException {
|
||||||
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
||||||
OpenPgpSignatureResult signatureResult = new OpenPgpSignatureResult();
|
OpenPgpSignatureResult signatureResult = new OpenPgpSignatureResult();
|
||||||
// cleartext signatures are never encrypted ;)
|
// cleartext signatures are never encrypted ;)
|
||||||
@ -578,7 +617,8 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
||||||
if (sigList == null) {
|
if (sigList == null) {
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_corrupt_data));
|
// throw new PgpGeneralException(mContext.getString(R.string.error_corrupt_data));
|
||||||
|
throw new InvalidDataException();
|
||||||
}
|
}
|
||||||
PGPSignature signature = null;
|
PGPSignature signature = null;
|
||||||
long signatureKeyId = 0;
|
long signatureKeyId = 0;
|
||||||
|
@ -300,7 +300,16 @@ public class OpenPgpService extends RemoteService {
|
|||||||
long inputLength = is.available();
|
long inputLength = is.available();
|
||||||
InputData inputData = new InputData(is, inputLength);
|
InputData inputData = new InputData(is, inputLength);
|
||||||
|
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||||
|
new ProviderHelper(this),
|
||||||
|
new PgpDecryptVerify.PassphraseCache() {
|
||||||
|
@Override
|
||||||
|
public String getCachedPassphrase(long masterKeyId) {
|
||||||
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
|
OpenPgpService.this, masterKeyId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputData, os);
|
||||||
builder.allowSymmetricDecryption(false) // no support for symmetric encryption
|
builder.allowSymmetricDecryption(false) // no support for symmetric encryption
|
||||||
.allowedKeyIds(allowedKeyIds) // allow only private keys associated with
|
.allowedKeyIds(allowedKeyIds) // allow only private keys associated with
|
||||||
// accounts of this app
|
// accounts of this app
|
||||||
|
@ -444,7 +444,16 @@ public class KeychainIntentService extends IntentService
|
|||||||
|
|
||||||
// verifyText and decrypt returning additional resultData values for the
|
// verifyText and decrypt returning additional resultData values for the
|
||||||
// verification of signatures
|
// verification of signatures
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, outStream);
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||||
|
new ProviderHelper(this),
|
||||||
|
new PgpDecryptVerify.PassphraseCache() {
|
||||||
|
@Override
|
||||||
|
public String getCachedPassphrase(long masterKeyId) {
|
||||||
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
|
KeychainIntentService.this, masterKeyId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputData, outStream);
|
||||||
builder.progressDialogUpdater(this);
|
builder.progressDialogUpdater(this);
|
||||||
|
|
||||||
builder.allowSymmetricDecryption(true)
|
builder.allowSymmetricDecryption(true)
|
||||||
|
Loading…
Reference in New Issue
Block a user