make PgpEncryptSign and PgpDecryptVerify subclasses of BaseOperation

This commit is contained in:
Vincent Breitmoser 2014-10-13 15:02:42 +02:00
parent e5c7d8dcd1
commit ee4d911baf
5 changed files with 36 additions and 120 deletions

View File

@ -105,6 +105,7 @@ public class PgpEncryptDecryptTest {
providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler()); providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
} }
/*
@Test @Test
public void testSymmetricEncryptDecrypt() { public void testSymmetricEncryptDecrypt() {

View File

@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import android.content.Context;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpMetadata;
@ -45,6 +46,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilde
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFactoryBuilder; import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFactoryBuilder;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
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;
@ -71,13 +73,11 @@ import java.util.Set;
/** /**
* This class uses a Builder pattern! * This class uses a Builder pattern!
*/ */
public class PgpDecryptVerify { public class PgpDecryptVerify extends BaseOperation {
private ProviderHelper mProviderHelper;
private PassphraseCacheInterface mPassphraseCache;
private InputData mData; private InputData mData;
private OutputStream mOutStream; private OutputStream mOutStream;
private Progressable mProgressable;
private boolean mAllowSymmetricDecryption; private boolean mAllowSymmetricDecryption;
private String mPassphrase; private String mPassphrase;
private Set<Long> mAllowedKeyIds; private Set<Long> mAllowedKeyIds;
@ -85,13 +85,12 @@ public class PgpDecryptVerify {
private byte[] mDecryptedSessionKey; private byte[] mDecryptedSessionKey;
private PgpDecryptVerify(Builder builder) { private PgpDecryptVerify(Builder builder) {
super(builder.mContext, builder.mProviderHelper, builder.mProgressable);
// private Constructor can only be called from Builder // private Constructor can only be called from Builder
this.mProviderHelper = builder.mProviderHelper;
this.mPassphraseCache = builder.mPassphraseCache;
this.mData = builder.mData; this.mData = builder.mData;
this.mOutStream = builder.mOutStream; this.mOutStream = builder.mOutStream;
this.mProgressable = builder.mProgressable;
this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption; this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption;
this.mPassphrase = builder.mPassphrase; this.mPassphrase = builder.mPassphrase;
this.mAllowedKeyIds = builder.mAllowedKeyIds; this.mAllowedKeyIds = builder.mAllowedKeyIds;
@ -101,6 +100,7 @@ public class PgpDecryptVerify {
public static class Builder { public static class Builder {
// mandatory parameter // mandatory parameter
private Context mContext;
private ProviderHelper mProviderHelper; private ProviderHelper mProviderHelper;
private PassphraseCacheInterface mPassphraseCache; private PassphraseCacheInterface mPassphraseCache;
private InputData mData; private InputData mData;
@ -114,19 +114,16 @@ public class PgpDecryptVerify {
private boolean mDecryptMetadataOnly = false; private boolean mDecryptMetadataOnly = false;
private byte[] mDecryptedSessionKey = null; private byte[] mDecryptedSessionKey = null;
public Builder(ProviderHelper providerHelper, PassphraseCacheInterface passphraseCache, public Builder(Context context, ProviderHelper providerHelper,
Progressable progressable,
InputData data, OutputStream outStream) { InputData data, OutputStream outStream) {
mContext = context;
mProviderHelper = providerHelper; mProviderHelper = providerHelper;
mPassphraseCache = passphraseCache; mProgressable = progressable;
mData = data; mData = data;
mOutStream = outStream; mOutStream = outStream;
} }
public Builder setProgressable(Progressable progressable) {
mProgressable = progressable;
return this;
}
public Builder setAllowSymmetricDecryption(boolean allowSymmetricDecryption) { public Builder setAllowSymmetricDecryption(boolean allowSymmetricDecryption) {
mAllowSymmetricDecryption = allowSymmetricDecryption; mAllowSymmetricDecryption = allowSymmetricDecryption;
return this; return this;
@ -165,18 +162,6 @@ public class PgpDecryptVerify {
} }
} }
public void updateProgress(int message, int current, int total) {
if (mProgressable != null) {
mProgressable.setProgress(message, current, total);
}
}
public void updateProgress(int current, int total) {
if (mProgressable != null) {
mProgressable.setProgress(current, total);
}
}
/** /**
* Decrypts and/or verifies data based on parameters of class * Decrypts and/or verifies data based on parameters of class
*/ */
@ -313,7 +298,7 @@ public class PgpDecryptVerify {
if (mPassphrase == null) { if (mPassphrase == null) {
try { try {
// returns "" if key has no passphrase // returns "" if key has no passphrase
mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId); mPassphrase = getCachedPassphrase(subKeyId);
log.add(LogType.MSG_DC_PASS_CACHED, indent +1); log.add(LogType.MSG_DC_PASS_CACHED, indent +1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) { } catch (PassphraseCacheInterface.NoSecretKeyException e) {
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent +1); log.add(LogType.MSG_DC_ERROR_NO_KEY, indent +1);

View File

@ -19,6 +19,8 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import android.content.Context;
import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.BCPGOutputStream; import org.spongycastle.bcpg.BCPGOutputStream;
import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.CompressionAlgorithmTags;
@ -34,6 +36,7 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@ -60,14 +63,11 @@ import java.util.LinkedList;
/** /**
* This class uses a Builder pattern! * This class uses a Builder pattern!
*/ */
public class PgpSignEncrypt { public class PgpSignEncrypt extends BaseOperation {
private ProviderHelper mProviderHelper;
private PassphraseCacheInterface mPassphraseCache;
private String mVersionHeader; private String mVersionHeader;
private InputData mData; private InputData mData;
private OutputStream mOutStream; private OutputStream mOutStream;
private Progressable mProgressable;
private boolean mEnableAsciiArmorOutput; private boolean mEnableAsciiArmorOutput;
private int mCompressionId; private int mCompressionId;
private long[] mEncryptionMasterKeyIds; private long[] mEncryptionMasterKeyIds;
@ -95,14 +95,13 @@ public class PgpSignEncrypt {
} }
private PgpSignEncrypt(Builder builder) { private PgpSignEncrypt(Builder builder) {
super(builder.mContext, builder.mProviderHelper, builder.mProgressable);
// private Constructor can only be called from Builder // private Constructor can only be called from Builder
this.mProviderHelper = builder.mProviderHelper;
this.mPassphraseCache = builder.mPassphraseCache;
this.mVersionHeader = builder.mVersionHeader; this.mVersionHeader = builder.mVersionHeader;
this.mData = builder.mData; this.mData = builder.mData;
this.mOutStream = builder.mOutStream; this.mOutStream = builder.mOutStream;
this.mProgressable = builder.mProgressable;
this.mEnableAsciiArmorOutput = builder.mEnableAsciiArmorOutput; this.mEnableAsciiArmorOutput = builder.mEnableAsciiArmorOutput;
this.mCompressionId = builder.mCompressionId; this.mCompressionId = builder.mCompressionId;
this.mEncryptionMasterKeyIds = builder.mEncryptionMasterKeyIds; this.mEncryptionMasterKeyIds = builder.mEncryptionMasterKeyIds;
@ -121,14 +120,14 @@ public class PgpSignEncrypt {
public static class Builder { public static class Builder {
// mandatory parameter // mandatory parameter
private Context mContext;
private ProviderHelper mProviderHelper; private ProviderHelper mProviderHelper;
private PassphraseCacheInterface mPassphraseCache; private Progressable mProgressable;
private InputData mData; private InputData mData;
private OutputStream mOutStream; private OutputStream mOutStream;
// optional // optional
private String mVersionHeader = null; private String mVersionHeader = null;
private Progressable mProgressable = null;
private boolean mEnableAsciiArmorOutput = false; private boolean mEnableAsciiArmorOutput = false;
private int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; private int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
private long[] mEncryptionMasterKeyIds = null; private long[] mEncryptionMasterKeyIds = null;
@ -144,10 +143,12 @@ public class PgpSignEncrypt {
private byte[] mNfcSignedHash = null; private byte[] mNfcSignedHash = null;
private Date mNfcCreationTimestamp = null; private Date mNfcCreationTimestamp = null;
public Builder(ProviderHelper providerHelper, PassphraseCacheInterface passphraseCache, public Builder(Context context, ProviderHelper providerHelper, Progressable progressable,
InputData data, OutputStream outStream) { InputData data, OutputStream outStream) {
mContext = context;
mProviderHelper = providerHelper; mProviderHelper = providerHelper;
mPassphraseCache = passphraseCache; mProgressable = progressable;
mData = data; mData = data;
mOutStream = outStream; mOutStream = outStream;
} }
@ -157,11 +158,6 @@ public class PgpSignEncrypt {
return this; return this;
} }
public Builder setProgressable(Progressable progressable) {
mProgressable = progressable;
return this;
}
public Builder setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) { public Builder setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput; mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this; return this;
@ -245,18 +241,6 @@ public class PgpSignEncrypt {
} }
} }
public void updateProgress(int message, int current, int total) {
if (mProgressable != null) {
mProgressable.setProgress(message, current, total);
}
}
public void updateProgress(int current, int total) {
if (mProgressable != null) {
mProgressable.setProgress(current, total);
}
}
/** /**
* Signs and/or encrypts data based on parameters of class * Signs and/or encrypts data based on parameters of class
*/ */
@ -324,7 +308,7 @@ public class PgpSignEncrypt {
if (mSignaturePassphrase == null) { if (mSignaturePassphrase == null) {
try { try {
// returns "" if key has no passphrase // returns "" if key has no passphrase
mSignaturePassphrase = mPassphraseCache.getCachedPassphrase(signKeyId); mSignaturePassphrase = getCachedPassphrase(signKeyId);
// TODO // TODO
// log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); // log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) { } catch (PassphraseCacheInterface.NoSecretKeyException e) {

View File

@ -34,11 +34,9 @@ import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.ui.NfcActivity; import org.sufficientlysecure.keychain.ui.NfcActivity;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
@ -76,28 +74,6 @@ public class OpenPgpService extends RemoteService {
static final String EMAIL_SEARCH_WHERE = Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED static final String EMAIL_SEARCH_WHERE = Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED
+ " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0";
private PassphraseCacheInterface passphraseCacheInterface = new PassphraseCacheInterface() {
@Override
public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try {
long masterKeyId = new ProviderHelper(getContext()).getMasterKeyId(subKeyId);
return getCachedPassphrase(masterKeyId, subKeyId);
} catch (NotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
}
@Override
public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
try {
return PassphraseCacheService.getCachedPassphrase(
getContext(), masterKeyId, subKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
}
};
/** /**
* Search database for key ids based on emails. * Search database for key ids based on emails.
* *
@ -304,7 +280,7 @@ public class OpenPgpService extends RemoteService {
// sign-only // sign-only
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
new ProviderHelper(getContext()), passphraseCacheInterface, this, new ProviderHelper(getContext()), null,
inputData, os inputData, os
); );
builder.setEnableAsciiArmorOutput(asciiArmor) builder.setEnableAsciiArmorOutput(asciiArmor)
@ -396,8 +372,7 @@ public class OpenPgpService extends RemoteService {
InputData inputData = new InputData(is, inputLength); InputData inputData = new InputData(is, inputLength);
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
new ProviderHelper(getContext()), passphraseCacheInterface, this, new ProviderHelper(getContext()), null, inputData, os
inputData, os
); );
builder.setEnableAsciiArmorOutput(asciiArmor) builder.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(PgpHelper.getVersionForHeader(this)) .setVersionHeader(PgpHelper.getVersionForHeader(this))
@ -513,8 +488,7 @@ public class OpenPgpService extends RemoteService {
InputData inputData = new InputData(is, inputLength); InputData inputData = new InputData(is, inputLength);
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
new ProviderHelper(getContext()), passphraseCacheInterface, this, new ProviderHelper(getContext()), null, inputData, os
inputData, os
); );
byte[] nfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); byte[] nfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY);

View File

@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.service;
import android.app.IntentService; import android.app.IntentService;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
@ -58,8 +57,6 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
@ -78,7 +75,6 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -91,7 +87,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* data from the activities or other apps, queues these intents, executes them, and stops itself * data from the activities or other apps, queues these intents, executes them, and stops itself
* after doing them. * after doing them.
*/ */
public class KeychainIntentService extends IntentService implements Progressable, PassphraseCacheInterface { public class KeychainIntentService extends IntentService implements Progressable {
/* extras that can be given by intent */ /* extras that can be given by intent */
public static final String EXTRA_MESSENGER = "messenger"; public static final String EXTRA_MESSENGER = "messenger";
@ -297,11 +293,9 @@ public class KeychainIntentService extends IntentService implements Progressable
// 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( PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
new ProviderHelper(this), this, new ProviderHelper(this), this, inputData, null
this, inputData, null
); );
builder.setProgressable(this) builder.setAllowSymmetricDecryption(true)
.setAllowSymmetricDecryption(true)
.setPassphrase(passphrase) .setPassphrase(passphrase)
.setDecryptMetadataOnly(true) .setDecryptMetadataOnly(true)
.setNfcState(nfcDecryptedSessionKey); .setNfcState(nfcDecryptedSessionKey);
@ -330,11 +324,10 @@ public class KeychainIntentService extends IntentService implements Progressable
// 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( PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
new ProviderHelper(this), this, this, new ProviderHelper(this), this,
inputData, outStream inputData, outStream
); );
builder.setProgressable(this) builder.setAllowSymmetricDecryption(true)
.setAllowSymmetricDecryption(true)
.setPassphrase(passphrase) .setPassphrase(passphrase)
.setNfcState(nfcDecryptedSessionKey); .setNfcState(nfcDecryptedSessionKey);
@ -591,10 +584,9 @@ public class KeychainIntentService extends IntentService implements Progressable
/* Operation */ /* Operation */
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
new ProviderHelper(this), this, inputData, outStream this, new ProviderHelper(this), this, inputData, outStream
); );
builder.setProgressable(this) builder.setEnableAsciiArmorOutput(useAsciiArmor)
.setEnableAsciiArmorOutput(useAsciiArmor)
.setVersionHeader(PgpHelper.getVersionForHeader(this)) .setVersionHeader(PgpHelper.getVersionForHeader(this))
.setCompressionId(compressionId) .setCompressionId(compressionId)
.setSymmetricEncryptionAlgorithm( .setSymmetricEncryptionAlgorithm(
@ -787,26 +779,6 @@ public class KeychainIntentService extends IntentService implements Progressable
} }
} }
@Override
public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try {
long masterKeyId = new ProviderHelper(this).getMasterKeyId(subKeyId);
return getCachedPassphrase(masterKeyId, subKeyId);
} catch (NotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
}
@Override
public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
try {
return PassphraseCacheService.getCachedPassphrase(
KeychainIntentService.this, masterKeyId, subKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
throw new PassphraseCacheInterface.NoSecretKeyException();
}
}
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_CANCEL.equals(intent.getAction())) { if (ACTION_CANCEL.equals(intent.getAction())) {