mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-24 07:58:50 -05:00
working version of DecryptVerifyResult
This commit is contained in:
parent
4c636a1471
commit
dbbefe2f41
@ -49,6 +49,8 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogLevel;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogType;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResultParcel.OperationLog;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
@ -70,6 +72,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class PgpDecryptVerify {
|
||||
private ProviderHelper mProviderHelper;
|
||||
private PassphraseCache mPassphraseCache;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
@ -83,6 +86,7 @@ public class PgpDecryptVerify {
|
||||
private PgpDecryptVerify(Builder builder) {
|
||||
// private Constructor can only be called from Builder
|
||||
this.mProviderHelper = builder.mProviderHelper;
|
||||
this.mPassphraseCache = builder.mPassphraseCache;
|
||||
this.mData = builder.mData;
|
||||
this.mOutStream = builder.mOutStream;
|
||||
|
||||
@ -97,6 +101,7 @@ public class PgpDecryptVerify {
|
||||
public static class Builder {
|
||||
// mandatory parameter
|
||||
private ProviderHelper mProviderHelper;
|
||||
private PassphraseCache mPassphraseCache;
|
||||
private InputData mData;
|
||||
private OutputStream mOutStream;
|
||||
|
||||
@ -108,8 +113,10 @@ public class PgpDecryptVerify {
|
||||
private boolean mDecryptMetadataOnly = false;
|
||||
private byte[] mDecryptedSessionKey = null;
|
||||
|
||||
public Builder(ProviderHelper providerHelper, InputData data, OutputStream outStream) {
|
||||
public Builder(ProviderHelper providerHelper, PassphraseCache passphraseCache,
|
||||
InputData data, OutputStream outStream) {
|
||||
this.mProviderHelper = providerHelper;
|
||||
this.mPassphraseCache = passphraseCache;
|
||||
this.mData = data;
|
||||
this.mOutStream = outStream;
|
||||
}
|
||||
@ -169,6 +176,16 @@ public class PgpDecryptVerify {
|
||||
}
|
||||
}
|
||||
|
||||
public interface PassphraseCache {
|
||||
public String getCachedPassphrase(long masterKeyId)
|
||||
throws NoSecretKeyException;
|
||||
}
|
||||
|
||||
public static class NoSecretKeyException extends Exception {
|
||||
public NoSecretKeyException() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts and/or verifies data based on parameters of class
|
||||
*/
|
||||
@ -286,12 +303,24 @@ public class PgpDecryptVerify {
|
||||
|
||||
encryptedDataAsymmetric = encData;
|
||||
|
||||
// if passphrase was not cached, return here indicating that a passphrase is missing!
|
||||
// if no passphrase was explicitly set try to get it from the cache service
|
||||
if (mPassphrase == null) {
|
||||
DecryptVerifyResult result =
|
||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log);
|
||||
result.setKeyIdPassphraseNeeded(subKeyId);
|
||||
return result;
|
||||
try {
|
||||
// returns "" if key has no passphrase
|
||||
mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId);
|
||||
} catch (NoSecretKeyException e) {
|
||||
// log.add(LogLevel.ERROR, LogType.MSG_DEC_ERROR_NO_KEY);
|
||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// if passphrase was not cached, return here
|
||||
// indicating that a passphrase is missing!
|
||||
if (mPassphrase == null) {
|
||||
DecryptVerifyResult result =
|
||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log);
|
||||
result.setKeyIdPassphraseNeeded(subKeyId);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// break out of while, only decrypt the first packet where we have a key
|
||||
|
@ -462,32 +462,23 @@ public class OpenPgpService extends RemoteService {
|
||||
.setDecryptMetadataOnly(decryptMetadataOnly)
|
||||
.setNfcState(nfcDecryptedSessionKey);
|
||||
|
||||
DecryptVerifyResult decryptVerifyResult;
|
||||
try {
|
||||
// TODO: currently does not support binary signed-only content
|
||||
decryptVerifyResult = builder.build().execute();
|
||||
// TODO: currently does not support binary signed-only content
|
||||
DecryptVerifyResult decryptVerifyResult = builder.build().execute();
|
||||
|
||||
// throw exceptions upwards to client with meaningful messages
|
||||
} catch (PgpDecryptVerify.InvalidDataException e) {
|
||||
throw new Exception(getString(R.string.error_invalid_data));
|
||||
} catch (PgpDecryptVerify.KeyExtractionException e) {
|
||||
throw new Exception(getString(R.string.error_could_not_extract_private_key));
|
||||
} catch (PgpDecryptVerify.WrongPassphraseException e) {
|
||||
throw new Exception(getString(R.string.error_wrong_passphrase));
|
||||
} catch (PgpDecryptVerify.NoSecretKeyException e) {
|
||||
throw new Exception(getString(R.string.error_no_secret_key_found));
|
||||
} catch (PgpDecryptVerify.IntegrityCheckFailedException e) {
|
||||
throw new Exception(getString(R.string.error_integrity_check_failed));
|
||||
} catch (PgpDecryptVerify.NeedNfcDataException e) {
|
||||
// return PendingIntent to execute NFC activity
|
||||
return getNfcDecryptIntent(data, e.mPassphrase, e.mEncryptedSessionKey);
|
||||
}
|
||||
|
||||
if (DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE == decryptVerifyResult.getStatus()) {
|
||||
// get PendingIntent for passphrase input, add it to given params and return to client
|
||||
return getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
|
||||
} else if (DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE == decryptVerifyResult.getStatus()) {
|
||||
throw new PgpGeneralException("Decryption of symmetric content not supported by API!");
|
||||
if (decryptVerifyResult.isPending()) {
|
||||
switch (decryptVerifyResult.getResult()) {
|
||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
||||
return getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
|
||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
||||
throw new PgpGeneralException(
|
||||
"Decryption of symmetric content not supported by API!");
|
||||
case DecryptVerifyResult.RESULT_PENDING_NFC:
|
||||
// TODO get passphrase here? currently not in DecryptVerifyResult
|
||||
return getNfcDecryptIntent(
|
||||
data, null, decryptVerifyResult.getNfcEncryptedSessionKey());
|
||||
}
|
||||
throw new PgpGeneralException(
|
||||
"Encountered unhandled type of pending action not supported by API!");
|
||||
}
|
||||
|
||||
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
|
||||
|
@ -337,15 +337,22 @@ public class KeychainIntentService extends IntentService implements Progressable
|
||||
|
||||
Bundle resultData = new Bundle();
|
||||
|
||||
/* TODO find passphrase from cache, if not provided
|
||||
return PassphraseCacheService.getCachedPassphrase(
|
||||
KeychainIntentService.this, masterKeyId);
|
||||
*/
|
||||
|
||||
// verifyText and decrypt returning additional resultData values for the
|
||||
// verification of signatures
|
||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||
new ProviderHelper(this), inputData, outStream
|
||||
new ProviderHelper(this),
|
||||
new PgpDecryptVerify.PassphraseCache() {
|
||||
@Override
|
||||
public String getCachedPassphrase(long masterKeyId) {
|
||||
try {
|
||||
return PassphraseCacheService.getCachedPassphrase(
|
||||
KeychainIntentService.this, masterKeyId);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
inputData, outStream
|
||||
);
|
||||
builder.setProgressable(this)
|
||||
.setAllowSymmetricDecryption(true)
|
||||
@ -378,15 +385,22 @@ public class KeychainIntentService extends IntentService implements Progressable
|
||||
|
||||
Bundle resultData = new Bundle();
|
||||
|
||||
/* TODO find passphrase from cache, if not provided
|
||||
return PassphraseCacheService.getCachedPassphrase(
|
||||
KeychainIntentService.this, masterKeyId);
|
||||
*/
|
||||
|
||||
// verifyText and decrypt returning additional resultData values for the
|
||||
// verification of signatures
|
||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||
new ProviderHelper(this), inputData, null
|
||||
new ProviderHelper(this),
|
||||
new PgpDecryptVerify.PassphraseCache() {
|
||||
@Override
|
||||
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
||||
try {
|
||||
return PassphraseCacheService.getCachedPassphrase(
|
||||
KeychainIntentService.this, masterKeyId);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
throw new PgpDecryptVerify.NoSecretKeyException();
|
||||
}
|
||||
}
|
||||
},
|
||||
inputData, null
|
||||
);
|
||||
builder.setProgressable(this)
|
||||
.setAllowSymmetricDecryption(true)
|
||||
|
@ -18,7 +18,6 @@
|
||||
package org.sufficientlysecure.keychain.service.results;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpMetadata;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
@ -34,7 +33,7 @@ public class DecryptVerifyResult extends OperationResultParcel {
|
||||
public static final int RESULT_PENDING_NFC = RESULT_PENDING +48;
|
||||
|
||||
long mKeyIdPassphraseNeeded;
|
||||
byte[] mSessionKey;
|
||||
byte[] mNfcSessionKey;
|
||||
|
||||
OpenPgpSignatureResult mSignatureResult;
|
||||
OpenPgpMetadata mDecryptMetadata;
|
||||
@ -48,7 +47,11 @@ public class DecryptVerifyResult extends OperationResultParcel {
|
||||
}
|
||||
|
||||
public void setNfcEncryptedSessionKey(byte[] sessionKey) {
|
||||
mSessionKey = sessionKey;
|
||||
mNfcSessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public byte[] getNfcEncryptedSessionKey() {
|
||||
return mNfcSessionKey;
|
||||
}
|
||||
|
||||
public OpenPgpSignatureResult getSignatureResult() {
|
||||
@ -80,7 +83,7 @@ public class DecryptVerifyResult extends OperationResultParcel {
|
||||
mKeyIdPassphraseNeeded = source.readLong();
|
||||
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
||||
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
|
||||
mSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
|
||||
mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
@ -92,9 +95,9 @@ public class DecryptVerifyResult extends OperationResultParcel {
|
||||
dest.writeLong(mKeyIdPassphraseNeeded);
|
||||
dest.writeParcelable(mSignatureResult, 0);
|
||||
dest.writeParcelable(mDecryptMetadata, 0);
|
||||
if (mSessionKey != null) {
|
||||
if (mNfcSessionKey != null) {
|
||||
dest.writeInt(1);
|
||||
dest.writeByteArray(mSessionKey);
|
||||
dest.writeByteArray(mNfcSessionKey);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
|
@ -261,13 +261,18 @@ public class DecryptFileFragment extends DecryptFragment {
|
||||
DecryptVerifyResult result =
|
||||
returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT);
|
||||
|
||||
switch (result.getResult()) {
|
||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
||||
showPassphraseDialog(result.getKeyIdPassphraseNeeded());
|
||||
return;
|
||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
||||
showPassphraseDialog(Constants.key.symmetric);
|
||||
return;
|
||||
if (result.isPending()) {
|
||||
switch (result.getResult()) {
|
||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
||||
showPassphraseDialog(result.getKeyIdPassphraseNeeded());
|
||||
return;
|
||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
||||
showPassphraseDialog(Constants.key.symmetric);
|
||||
return;
|
||||
}
|
||||
// error, we can't work with this!
|
||||
result.createNotify(getActivity());
|
||||
return;
|
||||
}
|
||||
|
||||
// display signature result in activity
|
||||
|
@ -146,13 +146,18 @@ public class DecryptMessageFragment extends DecryptFragment {
|
||||
DecryptVerifyResult result =
|
||||
returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT);
|
||||
|
||||
switch (result.getResult()) {
|
||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
||||
showPassphraseDialog(result.getKeyIdPassphraseNeeded());
|
||||
return;
|
||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
||||
showPassphraseDialog(Constants.key.symmetric);
|
||||
return;
|
||||
if (result.isPending()) {
|
||||
switch (result.getResult()) {
|
||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
||||
showPassphraseDialog(result.getKeyIdPassphraseNeeded());
|
||||
return;
|
||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
||||
showPassphraseDialog(Constants.key.symmetric);
|
||||
return;
|
||||
}
|
||||
// error, we can't work with this!
|
||||
result.createNotify(getActivity());
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] decryptedMessage = returnData
|
||||
@ -160,6 +165,8 @@ public class DecryptMessageFragment extends DecryptFragment {
|
||||
mMessage.setText(new String(decryptedMessage));
|
||||
mMessage.setHorizontallyScrolling(false);
|
||||
|
||||
result.createNotify(getActivity());
|
||||
|
||||
// display signature result in activity
|
||||
onResult(result);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user