From 4c636a1471ac1013574a3d1446549a652c690b47 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 13 Sep 2014 17:54:10 +0200 Subject: [PATCH 1/4] introduce OperationResultParcel for PgpDecryptVerify operations (WIP) --- .../support/PgpVerifyTestingHelper.java | 4 +- .../keychain/pgp/PgpDecryptVerify.java | 187 ++++++++---------- .../keychain/remote/OpenPgpService.java | 8 +- .../service/KeychainIntentService.java | 54 ++--- .../results/DecryptVerifyResult.java} | 71 ++++--- .../keychain/ui/DecryptFileFragment.java | 76 +++---- .../keychain/ui/DecryptFragment.java | 4 +- .../keychain/ui/DecryptMessageFragment.java | 33 ++-- 8 files changed, 204 insertions(+), 233 deletions(-) rename OpenKeychain/src/main/java/org/sufficientlysecure/keychain/{pgp/PgpDecryptVerifyResult.java => service/results/DecryptVerifyResult.java} (53%) diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/PgpVerifyTestingHelper.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/PgpVerifyTestingHelper.java index dd5786512..a0147b238 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/PgpVerifyTestingHelper.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/PgpVerifyTestingHelper.java @@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.support; import android.content.Context; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.InputData; @@ -56,7 +56,7 @@ public class PgpVerifyTestingHelper { OutputStream outStream = new ByteArrayOutputStream(); PgpDecryptVerify verify = new PgpDecryptVerify.Builder(providerHelper, passphraseCache, data, outStream).build(); - PgpDecryptVerifyResult result = verify.execute(); + DecryptVerifyResult result = verify.execute(); return result.getSignatureResult().getStatus(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index b2b633ed7..d7107d695 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -48,6 +48,8 @@ import org.sufficientlysecure.keychain.R; 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.OperationLog; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -68,7 +70,6 @@ import java.util.Set; */ public class PgpDecryptVerify { private ProviderHelper mProviderHelper; - private PassphraseCache mPassphraseCache; private InputData mData; private OutputStream mOutStream; @@ -82,7 +83,6 @@ 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,7 +97,6 @@ public class PgpDecryptVerify { public static class Builder { // mandatory parameter private ProviderHelper mProviderHelper; - private PassphraseCache mPassphraseCache; private InputData mData; private OutputStream mOutStream; @@ -109,10 +108,8 @@ public class PgpDecryptVerify { private boolean mDecryptMetadataOnly = false; private byte[] mDecryptedSessionKey = null; - public Builder(ProviderHelper providerHelper, PassphraseCache passphraseCache, - InputData data, OutputStream outStream) { + public Builder(ProviderHelper providerHelper, InputData data, OutputStream outStream) { this.mProviderHelper = providerHelper; - this.mPassphraseCache = passphraseCache; this.mData = data; this.mOutStream = outStream; } @@ -172,78 +169,44 @@ public class PgpDecryptVerify { } } - public interface PassphraseCache { - public String getCachedPassphrase(long masterKeyId) - throws NoSecretKeyException; - } - - 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() { - } - } - - public static class NeedNfcDataException extends Exception { - public byte[] mEncryptedSessionKey; - public String mPassphrase; - - public NeedNfcDataException(byte[] encryptedSessionKey, String passphrase) { - mEncryptedSessionKey = encryptedSessionKey; - mPassphrase = passphrase; - } - } - /** * Decrypts and/or verifies data based on parameters of class */ - public PgpDecryptVerifyResult execute() - throws IOException, PGPException, SignatureException, - WrongPassphraseException, NoSecretKeyException, KeyExtractionException, - InvalidDataException, IntegrityCheckFailedException, NeedNfcDataException { - // automatically works with ascii armor input and binary - InputStream in = PGPUtil.getDecoderStream(mData.getInputStream()); - if (in instanceof ArmoredInputStream) { - ArmoredInputStream aIn = (ArmoredInputStream) in; - // it is ascii armored - Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine()); + public DecryptVerifyResult execute() { + try { + // automatically works with ascii armor input and binary + InputStream in = PGPUtil.getDecoderStream(mData.getInputStream()); - if (aIn.isClearText()) { - // a cleartext signature, verify it with the other method - return verifyCleartextSignature(aIn); + if (in instanceof ArmoredInputStream) { + ArmoredInputStream aIn = (ArmoredInputStream) in; + // it is ascii armored + Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine()); + + if (aIn.isClearText()) { + // a cleartext signature, verify it with the other method + return verifyCleartextSignature(aIn); + } + // else: ascii armored encryption! go on... } - // else: ascii armored encryption! go on... - } - return decryptVerify(in); + return decryptVerify(in); + } catch (PGPException e) { + OperationLog log = new OperationLog(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_PGP_EXCEPTION); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); + } catch (IOException e) { + OperationLog log = new OperationLog(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_IO); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); + } } /** * Decrypt and/or verifies binary or ascii armored pgp */ - private PgpDecryptVerifyResult decryptVerify(InputStream in) - throws IOException, PGPException, SignatureException, - WrongPassphraseException, KeyExtractionException, NoSecretKeyException, - InvalidDataException, IntegrityCheckFailedException, NeedNfcDataException { - PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); + private DecryptVerifyResult decryptVerify(InputStream in) throws IOException, PGPException { + + OperationLog log = new OperationLog(); PGPObjectFactory pgpF = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator()); PGPEncryptedDataList enc; @@ -259,7 +222,8 @@ public class PgpDecryptVerify { } if (enc == null) { - throw new InvalidDataException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_DATA) + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } InputStream clear; @@ -322,18 +286,12 @@ public class PgpDecryptVerify { encryptedDataAsymmetric = encData; - // if no passphrase was explicitly set try to get it from the cache service + // if passphrase was not cached, return here indicating that a passphrase is missing! if (mPassphrase == null) { - // returns "" if key has no passphrase - mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId); - - // if passphrase was not cached, return here - // indicating that a passphrase is missing! - if (mPassphrase == null) { - result.setKeyIdPassphraseNeeded(subKeyId); - result.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED); - return result; - } + 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 @@ -351,8 +309,7 @@ public class PgpDecryptVerify { // if no passphrase is given, return here // indicating that a passphrase is missing! if (mPassphrase == null) { - result.setStatus(PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED); - return result; + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE, log); } // break out of while, only decrypt the first packet @@ -379,10 +336,12 @@ public class PgpDecryptVerify { updateProgress(R.string.progress_extracting_key, currentProgress, 100); try { if (!secretEncryptionKey.unlock(mPassphrase)) { - throw new WrongPassphraseException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_BAD_PASSPHRASE); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } catch (PgpGeneralException e) { - throw new KeyExtractionException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_EXTRACT_KEY); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } currentProgress += 2; @@ -393,12 +352,19 @@ public class PgpDecryptVerify { = secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey); clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); } catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) { - throw new NeedNfcDataException(e.encryptedSessionKey, mPassphrase); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_NFC_INTERACTION); + + DecryptVerifyResult result = + new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log); + result.setNfcEncryptedSessionKey(e.encryptedSessionKey); + // TODO save passphrase here? + return result; } encryptedData = encryptedDataAsymmetric; } else { // no packet has been found where we have the corresponding secret key in our db - throw new NoSecretKeyException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_MISSING_SECRET_KEY); + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } PGPObjectFactory plainFact = new PGPObjectFactory(clear, new JcaKeyFingerprintCalculator()); @@ -468,6 +434,8 @@ public class PgpDecryptVerify { dataChunk = plainFact.nextObject(); } + OpenPgpMetadata metadata; + if (dataChunk instanceof PGPLiteralData) { currentProgress += 4; updateProgress(R.string.progress_decrypting, currentProgress, 100); @@ -503,17 +471,17 @@ public class PgpDecryptVerify { } } - OpenPgpMetadata metadata = new OpenPgpMetadata( + metadata = new OpenPgpMetadata( originalFilename, mimeType, literalData.getModificationTime().getTime(), originalSize); - result.setDecryptMetadata(metadata); - - Log.d(Constants.TAG, "metadata: " + metadata); // return here if we want to decrypt the metadata only if (mDecryptMetadataOnly) { + DecryptVerifyResult result = + new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + result.setDecryptMetadata(metadata); return result; } @@ -569,18 +537,19 @@ public class PgpDecryptVerify { boolean validSignature = signature.verify(messageSignature); signatureResultBuilder.setValidSignature(validSignature); } + } else { + // If there is no literalData, we don't have any metadata + metadata = null; } if (encryptedData.isIntegrityProtected()) { updateProgress(R.string.progress_verifying_integrity, 95, 100); if (encryptedData.verify()) { - // passed - Log.d(Constants.TAG, "Integrity verification: success!"); + // log.add(LogLevel.INFO, LogType.MSG_DC_INTEGRITY_CHECK_OK) } else { - // failed - Log.d(Constants.TAG, "Integrity verification: failed!"); - throw new IntegrityCheckFailedException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK) + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } else { // no integrity check @@ -590,14 +559,20 @@ public class PgpDecryptVerify { // Handle missing integrity protection like failed integrity protection! // The MDC packet can be stripped by an attacker! if (!signatureResultBuilder.isValidSignature()) { - throw new IntegrityCheckFailedException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK) + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } updateProgress(R.string.progress_done, 100, 100); + // Return a positive result, with metadata and verification info + DecryptVerifyResult result = + new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + result.setDecryptMetadata(metadata); result.setSignatureResult(signatureResultBuilder.build()); return result; + } /** @@ -607,9 +582,11 @@ public class PgpDecryptVerify { * The method is heavily based on * pg/src/main/java/org/spongycastle/openpgp/examples/ClearSignedFileProcessor.java */ - private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn) - throws IOException, PGPException, SignatureException, InvalidDataException { - PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); + private DecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn) + throws IOException, PGPException { + + OperationLog log = new OperationLog(); + OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); // cleartext signatures are never encrypted ;) signatureResultBuilder.setSignatureOnly(true); @@ -643,7 +620,8 @@ public class PgpDecryptVerify { PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); if (sigList == null) { - throw new InvalidDataException(); + // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_DATA) + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } CanonicalizedPublicKeyRing signingRing = null; @@ -686,7 +664,7 @@ public class PgpDecryptVerify { } } - if (signature != null) { + if (signature != null) try { updateProgress(R.string.progress_verifying_signature, 90, 100); InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText)); @@ -708,13 +686,16 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(); - signatureResultBuilder.setValidSignature(validSignature); + + } catch (SignatureException e) { + return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } - result.setSignatureResult(signatureResultBuilder.build()); - updateProgress(R.string.progress_done, 100, 100); + + DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + result.setSignatureResult(signatureResultBuilder.build()); return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index fc8f1c7e4..1092fe7b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -34,7 +34,7 @@ import org.sufficientlysecure.keychain.nfc.NfcActivity; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; @@ -462,7 +462,7 @@ public class OpenPgpService extends RemoteService { .setDecryptMetadataOnly(decryptMetadataOnly) .setNfcState(nfcDecryptedSessionKey); - PgpDecryptVerifyResult decryptVerifyResult; + DecryptVerifyResult decryptVerifyResult; try { // TODO: currently does not support binary signed-only content decryptVerifyResult = builder.build().execute(); @@ -483,10 +483,10 @@ public class OpenPgpService extends RemoteService { return getNfcDecryptIntent(data, e.mPassphrase, e.mEncryptedSessionKey); } - if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { + 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 (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { + } else if (DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE == decryptVerifyResult.getStatus()) { throw new PgpGeneralException("Decryption of symmetric content not supported by API!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 92917fa51..2366e0237 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -41,7 +41,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpImportExport; import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; @@ -337,28 +337,21 @@ 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), - 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, outStream + new ProviderHelper(this), inputData, outStream ); builder.setProgressable(this) .setAllowSymmetricDecryption(true) .setPassphrase(passphrase); - PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); + DecryptVerifyResult decryptVerifyResult = builder.build().execute(); outStream.close(); @@ -385,29 +378,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), - 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 + new ProviderHelper(this), inputData, null ); builder.setProgressable(this) .setAllowSymmetricDecryption(true) .setPassphrase(passphrase) .setDecryptMetadataOnly(true); - PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); + DecryptVerifyResult decryptVerifyResult = builder.build().execute(); resultData.putParcelable(RESULT_DECRYPT_VERIFY_RESULT, decryptVerifyResult); @@ -785,16 +771,6 @@ public class KeychainIntentService extends IntentService implements Progressable message = getString(R.string.error_no_signature_passphrase); } else if (e instanceof PgpSignEncrypt.NoSigningKeyException) { message = getString(R.string.error_no_signature_key); - } else if (e instanceof PgpDecryptVerify.InvalidDataException) { - message = getString(R.string.error_invalid_data); - } else if (e instanceof PgpDecryptVerify.KeyExtractionException) { - message = getString(R.string.error_could_not_extract_private_key); - } else if (e instanceof PgpDecryptVerify.WrongPassphraseException) { - message = getString(R.string.error_wrong_passphrase); - } else if (e instanceof PgpDecryptVerify.NoSecretKeyException) { - message = getString(R.string.error_no_secret_key_found); - } else if (e instanceof PgpDecryptVerify.IntegrityCheckFailedException) { - message = getString(R.string.error_integrity_check_failed); } else { message = e.getMessage(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java similarity index 53% rename from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java rename to OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java index 506f48c52..909f9f9be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.sufficientlysecure.keychain.pgp; +package org.sufficientlysecure.keychain.service.results; import android.os.Parcel; import android.os.Parcelable; @@ -23,25 +23,22 @@ import android.os.Parcelable; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; -public class PgpDecryptVerifyResult implements Parcelable { - public static final int SUCCESS = 1; - public static final int KEY_PASSHRASE_NEEDED = 2; - public static final int SYMMETRIC_PASSHRASE_NEEDED = 3; +public class DecryptVerifyResult extends OperationResultParcel { + + // the fourth bit indicates a "data pending" result! + public static final int RESULT_PENDING = 8; + + // fifth to sixth bit in addition indicate specific type of pending + public static final int RESULT_PENDING_ASYM_PASSPHRASE = RESULT_PENDING +16; + public static final int RESULT_PENDING_SYM_PASSPHRASE = RESULT_PENDING +32; + public static final int RESULT_PENDING_NFC = RESULT_PENDING +48; - int mStatus; long mKeyIdPassphraseNeeded; + byte[] mSessionKey; OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; - public int getStatus() { - return mStatus; - } - - public void setStatus(int status) { - mStatus = status; - } - public long getKeyIdPassphraseNeeded() { return mKeyIdPassphraseNeeded; } @@ -50,6 +47,10 @@ public class PgpDecryptVerifyResult implements Parcelable { mKeyIdPassphraseNeeded = keyIdPassphraseNeeded; } + public void setNfcEncryptedSessionKey(byte[] sessionKey) { + mSessionKey = sessionKey; + } + public OpenPgpSignatureResult getSignatureResult() { return mSignatureResult; } @@ -66,41 +67,47 @@ public class PgpDecryptVerifyResult implements Parcelable { mDecryptMetadata = decryptMetadata; } - public PgpDecryptVerifyResult() { - + public boolean isPending() { + return (mResult & RESULT_PENDING) != 0; } - public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) { - this.mStatus = b.mStatus; - this.mKeyIdPassphraseNeeded = b.mKeyIdPassphraseNeeded; - this.mSignatureResult = b.mSignatureResult; - this.mDecryptMetadata = b.mDecryptMetadata; + public DecryptVerifyResult(int result, OperationLog log) { + super(result, log); } + public DecryptVerifyResult(Parcel source) { + super(source); + mKeyIdPassphraseNeeded = source.readLong(); + mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); + mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); + mSessionKey = source.readInt() != 0 ? source.createByteArray() : null; + } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mStatus); + super.writeToParcel(dest, flags); dest.writeLong(mKeyIdPassphraseNeeded); dest.writeParcelable(mSignatureResult, 0); dest.writeParcelable(mDecryptMetadata, 0); + if (mSessionKey != null) { + dest.writeInt(1); + dest.writeByteArray(mSessionKey); + } else { + dest.writeInt(0); + } } - public static final Creator CREATOR = new Creator() { - public PgpDecryptVerifyResult createFromParcel(final Parcel source) { - PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult(); - vr.mStatus = source.readInt(); - vr.mKeyIdPassphraseNeeded = source.readLong(); - vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); - vr.mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); - return vr; + public static final Creator CREATOR = new Creator() { + public DecryptVerifyResult createFromParcel(final Parcel source) { + return new DecryptVerifyResult(source); } - public PgpDecryptVerifyResult[] newArray(final int size) { - return new PgpDecryptVerifyResult[size]; + public DecryptVerifyResult[] newArray(final int size) { + return new DecryptVerifyResult[size]; } }; + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 845fbfa3b..ec0f68ced 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -36,7 +36,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; @@ -178,19 +178,20 @@ public class DecryptFileFragment extends DecryptFragment { // get returned data bundle Bundle returnData = message.getData(); - PgpDecryptVerifyResult decryptVerifyResult = + DecryptVerifyResult result = returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { - showPassphraseDialogForFilename(decryptVerifyResult.getKeyIdPassphraseNeeded()); - } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == - decryptVerifyResult.getStatus()) { - showPassphraseDialogForFilename(Constants.key.symmetric); - } else { - - // go on... - askForOutputFilename(decryptVerifyResult.getDecryptMetadata().getFilename()); + switch (result.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + showPassphraseDialog(result.getKeyIdPassphraseNeeded()); + return; + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + showPassphraseDialog(Constants.key.symmetric); + return; } + + // go on... + askForOutputFilename(result.getDecryptMetadata().getFilename()); } } }; @@ -257,35 +258,38 @@ public class DecryptFileFragment extends DecryptFragment { // get returned data bundle Bundle returnData = message.getData(); - PgpDecryptVerifyResult decryptVerifyResult = + DecryptVerifyResult result = returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { - showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); - } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == - decryptVerifyResult.getStatus()) { - showPassphraseDialog(Constants.key.symmetric); - } else { - // display signature result in activity - onResult(decryptVerifyResult); - - if (mDeleteAfter.isChecked()) { - // Create and show dialog to delete original file - DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - setInputUri(null); - } - - /* - // A future open after decryption feature - if () { - Intent viewFile = new Intent(Intent.ACTION_VIEW); - viewFile.setData(mOutputUri); - startActivity(viewFile); - } - */ + switch (result.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + showPassphraseDialog(result.getKeyIdPassphraseNeeded()); + return; + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + showPassphraseDialog(Constants.key.symmetric); + return; } + + // display signature result in activity + onResult(result); + + if (mDeleteAfter.isChecked()) { + // Create and show dialog to delete original file + DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); + deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); + setInputUri(null); + } + + /* + // A future open after decryption feature + if () { + Intent viewFile = new Intent(Intent.ACTION_VIEW); + viewFile.setData(mOutputUri); + startActivity(viewFile); + } + */ } + } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 9abe48d64..ff20d0e98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -34,7 +34,7 @@ import android.widget.TextView; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; @@ -100,7 +100,7 @@ public abstract class DecryptFragment extends Fragment { } } - protected void onResult(PgpDecryptVerifyResult decryptVerifyResult) { + protected void onResult(DecryptVerifyResult decryptVerifyResult) { OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); mSignatureKeyId = 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index cf7a0b4b8..01ea4b042 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -31,7 +31,7 @@ import android.widget.EditText; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -143,24 +143,27 @@ public class DecryptMessageFragment extends DecryptFragment { // get returned data bundle Bundle returnData = message.getData(); - PgpDecryptVerifyResult decryptVerifyResult = + DecryptVerifyResult result = returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { - showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); - } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == - decryptVerifyResult.getStatus()) { - showPassphraseDialog(Constants.key.symmetric); - } else { - byte[] decryptedMessage = returnData - .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); - mMessage.setText(new String(decryptedMessage)); - mMessage.setHorizontallyScrolling(false); - - // display signature result in activity - onResult(decryptVerifyResult); + switch (result.getResult()) { + case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE: + showPassphraseDialog(result.getKeyIdPassphraseNeeded()); + return; + case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE: + showPassphraseDialog(Constants.key.symmetric); + return; } + + byte[] decryptedMessage = returnData + .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); + mMessage.setText(new String(decryptedMessage)); + mMessage.setHorizontallyScrolling(false); + + // display signature result in activity + onResult(result); } + } }; From dbbefe2f412b8c59690a01d3fda48627ceec6063 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 13 Sep 2014 19:30:10 +0200 Subject: [PATCH 2/4] working version of DecryptVerifyResult --- .../keychain/pgp/PgpDecryptVerify.java | 41 ++++++++++++++++--- .../keychain/remote/OpenPgpService.java | 41 ++++++++----------- .../service/KeychainIntentService.java | 38 +++++++++++------ .../service/results/DecryptVerifyResult.java | 15 ++++--- .../keychain/ui/DecryptFileFragment.java | 19 +++++---- .../keychain/ui/DecryptMessageFragment.java | 21 ++++++---- 6 files changed, 112 insertions(+), 63 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index d7107d695..4e4e8c4e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 1092fe7b4..3dc6f8a6e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -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(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2366e0237..966c43597 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -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) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java index 909f9f9be..e7ac209bf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/DecryptVerifyResult.java @@ -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); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index ec0f68ced..7d9b2b9b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 01ea4b042..75e38d5c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -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); } From efd9d1626e0d692d287185deb16d295c4636be48 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 13 Sep 2014 21:14:06 +0200 Subject: [PATCH 3/4] add a ton of logging to DecryptVerify --- .../keychain/pgp/PgpDecryptVerify.java | 112 ++++++++++++++---- .../results/OperationResultParcel.java | 38 ++++++ .../keychain/ui/DecryptMessageFragment.java | 4 +- OpenKeychain/src/main/res/values/strings.xml | 38 ++++++ 4 files changed, 166 insertions(+), 26 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 4e4e8c4e0..769a48a8e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -206,14 +206,14 @@ public class PgpDecryptVerify { // else: ascii armored encryption! go on... } - return decryptVerify(in); + return decryptVerify(in, 0); } catch (PGPException e) { OperationLog log = new OperationLog(); - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_PGP_EXCEPTION); + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_PGP_EXCEPTION, 1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } catch (IOException e) { OperationLog log = new OperationLog(); - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_IO); + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_IO, 1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } @@ -221,10 +221,13 @@ public class PgpDecryptVerify { /** * Decrypt and/or verifies binary or ascii armored pgp */ - private DecryptVerifyResult decryptVerify(InputStream in) throws IOException, PGPException { + private DecryptVerifyResult decryptVerify(InputStream in, int indent) throws IOException, PGPException { OperationLog log = new OperationLog(); + log.add(LogLevel.START, LogType.MSG_DC, indent); + indent += 1; + PGPObjectFactory pgpF = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator()); PGPEncryptedDataList enc; Object o = pgpF.nextObject(); @@ -239,7 +242,7 @@ public class PgpDecryptVerify { } if (enc == null) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_DATA) + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_SIGLIST, indent); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -252,35 +255,44 @@ public class PgpDecryptVerify { Iterator it = enc.getEncryptedDataObjects(); boolean asymmetricPacketFound = false; boolean symmetricPacketFound = false; + boolean anyPacketFound = false; + // go through all objects and find one we can decrypt while (it.hasNext()) { Object obj = it.next(); if (obj instanceof PGPPublicKeyEncryptedData) { + anyPacketFound = true; + currentProgress += 2; updateProgress(R.string.progress_finding_key, currentProgress, 100); PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - long subKeyId = encData.getKeyID(); + log.add(LogLevel.DEBUG, LogType.MSG_DC_ASYM, indent, + PgpKeyHelper.convertKeyIdToHex(subKeyId)); + CanonicalizedSecretKeyRing secretKeyRing; try { // get actual keyring object based on master key id secretKeyRing = mProviderHelper.getCanonicalizedSecretKeyRing( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(encData.getKeyID()) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId) ); } catch (ProviderHelper.NotFoundException e) { // continue with the next packet in the while loop + log.add(LogLevel.DEBUG, LogType.MSG_DC_ASKIP_NO_KEY, indent +1); continue; } if (secretKeyRing == null) { // continue with the next packet in the while loop + log.add(LogLevel.DEBUG, LogType.MSG_DC_ASKIP_NO_KEY, indent +1); continue; } // get subkey which has been used for this encryption packet secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId); if (secretEncryptionKey == null) { - // continue with the next packet in the while loop + // should actually never happen, so no need to be more specific. + log.add(LogLevel.DEBUG, LogType.MSG_DC_ASKIP_NO_KEY, indent +1); continue; } @@ -294,6 +306,7 @@ public class PgpDecryptVerify { if (!mAllowedKeyIds.contains(masterKeyId)) { // this key is in our db, but NOT allowed! // continue with the next packet in the while loop + log.add(LogLevel.DEBUG, LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent +1); continue; } } @@ -308,14 +321,15 @@ public class PgpDecryptVerify { try { // returns "" if key has no passphrase mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId); + log.add(LogLevel.DEBUG, LogType.MSG_DC_PASS_CACHED, indent +1); } catch (NoSecretKeyException e) { - // log.add(LogLevel.ERROR, LogType.MSG_DEC_ERROR_NO_KEY); + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_NO_KEY, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } - // if passphrase was not cached, return here - // indicating that a passphrase is missing! + // if passphrase was not cached, return here indicating that a passphrase is missing! if (mPassphrase == null) { + log.add(LogLevel.INFO, LogType.MSG_DC_PENDING_PASSPHRASE, indent +1); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log); result.setKeyIdPassphraseNeeded(subKeyId); @@ -324,9 +338,18 @@ public class PgpDecryptVerify { } // break out of while, only decrypt the first packet where we have a key - // TODO???: There could be more pgp objects, which are not decrypted! break; - } else if (mAllowSymmetricDecryption && obj instanceof PGPPBEEncryptedData) { + + } else if (obj instanceof PGPPBEEncryptedData) { + anyPacketFound = true; + + log.add(LogLevel.DEBUG, LogType.MSG_DC_SYM, indent); + + if (! mAllowSymmetricDecryption) { + log.add(LogLevel.WARN, LogType.MSG_DC_SYM_SKIP, indent +1); + continue; + } + /* * When mAllowSymmetricDecryption == true and we find a data packet here, * we do not search for other available asymmetric packets! @@ -338,15 +361,30 @@ public class PgpDecryptVerify { // if no passphrase is given, return here // indicating that a passphrase is missing! if (mPassphrase == null) { + log.add(LogLevel.INFO, LogType.MSG_DC_PENDING_PASSPHRASE, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE, log); } // break out of while, only decrypt the first packet - // TODO???: There could be more pgp objects, which are not decrypted! break; } } + // More data, just acknowledge and ignore. + while (it.hasNext()) { + Object obj = it.next(); + if (obj instanceof PGPPublicKeyEncryptedData) { + log.add(LogLevel.WARN, LogType.MSG_DC_TRAIL_ASYM, 0); + } else if (obj instanceof PGPPBEEncryptedData) { + log.add(LogLevel.WARN, LogType.MSG_DC_TRAIL_SYM, 0); + } else { + log.add(LogLevel.WARN, LogType.MSG_DC_TRAIL_UNKNOWN, 0); + } + } + + log.add(LogLevel.DEBUG, LogType.MSG_DC_PREP_STREAMS, indent); + + // we made sure above one of these two would be true if (symmetricPacketFound) { currentProgress += 2; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); @@ -358,18 +396,20 @@ public class PgpDecryptVerify { mPassphrase.toCharArray()); clear = encryptedDataSymmetric.getDataStream(decryptorFactory); - encryptedData = encryptedDataSymmetric; + } else if (asymmetricPacketFound) { currentProgress += 2; updateProgress(R.string.progress_extracting_key, currentProgress, 100); + try { + log.add(LogLevel.WARN, LogType.MSG_DC_UNLOCKING, indent +1); if (!secretEncryptionKey.unlock(mPassphrase)) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_BAD_PASSPHRASE); + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } catch (PgpGeneralException e) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_EXTRACT_KEY); + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_EXTRACT_KEY, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -381,8 +421,7 @@ public class PgpDecryptVerify { = secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey); clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); } catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_NFC_INTERACTION); - + log.add(LogLevel.INFO, LogType.MSG_DC_PENDING_NFC, indent +1); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log); result.setNfcEncryptedSessionKey(e.encryptedSessionKey); @@ -391,8 +430,10 @@ public class PgpDecryptVerify { } encryptedData = encryptedDataAsymmetric; } else { + // If we didn't find any useful data, error out // no packet has been found where we have the corresponding secret key in our db - // log.add(LogLevel.ERROR, LogType.MSG_DC_MISSING_SECRET_KEY); + log.add(LogLevel.ERROR, + anyPacketFound ? LogType.MSG_DC_ERROR_NO_KEY : LogType.MSG_DC_ERROR_NO_DATA, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -403,7 +444,11 @@ public class PgpDecryptVerify { CanonicalizedPublicKeyRing signingRing = null; CanonicalizedPublicKey signingKey = null; + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR, indent); + indent += 1; + if (dataChunk instanceof PGPCompressedData) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_DECOMPRESS, indent +1); currentProgress += 2; updateProgress(R.string.progress_decompressing_data, currentProgress, 100); @@ -416,6 +461,7 @@ public class PgpDecryptVerify { PGPOnePassSignature signature = null; if (dataChunk instanceof PGPOnePassSignatureList) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_SIGNATURE, indent +1); currentProgress += 2; updateProgress(R.string.progress_processing_signature, currentProgress, 100); @@ -466,6 +512,8 @@ public class PgpDecryptVerify { OpenPgpMetadata metadata; if (dataChunk instanceof PGPLiteralData) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_DATA, indent +1); + indent += 2; currentProgress += 4; updateProgress(R.string.progress_decrypting, currentProgress, 100); @@ -506,8 +554,14 @@ public class PgpDecryptVerify { literalData.getModificationTime().getTime(), originalSize); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_FILE, indent +1); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_MIME, indent +1); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_TIME, indent +1); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_SIZE, indent +1); + // return here if we want to decrypt the metadata only if (mDecryptMetadataOnly) { + log.add(LogLevel.OK, LogType.MSG_DC_OK_META_ONLY, indent); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setDecryptMetadata(metadata); @@ -554,6 +608,7 @@ public class PgpDecryptVerify { if (signature != null) { updateProgress(R.string.progress_verifying_signature, 90, 100); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent); PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject(); PGPSignature messageSignature = signatureList.get(signatureIndex); @@ -564,8 +619,15 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(messageSignature); + if (validSignature) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent +1); + } else { + log.add(LogLevel.WARN, LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent +1); + } signatureResultBuilder.setValidSignature(validSignature); } + + indent -= 1; } else { // If there is no literalData, we don't have any metadata metadata = null; @@ -575,9 +637,9 @@ public class PgpDecryptVerify { updateProgress(R.string.progress_verifying_integrity, 95, 100); if (encryptedData.verify()) { - // log.add(LogLevel.INFO, LogType.MSG_DC_INTEGRITY_CHECK_OK) + log.add(LogLevel.INFO, LogType.MSG_DC_INTEGRITY_CHECK_OK, indent); } else { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK) + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } else { @@ -588,13 +650,15 @@ public class PgpDecryptVerify { // Handle missing integrity protection like failed integrity protection! // The MDC packet can be stripped by an attacker! if (!signatureResultBuilder.isValidSignature()) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK) + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } } updateProgress(R.string.progress_done, 100, 100); + log.add(LogLevel.OK, LogType.MSG_DC_OK, indent); + // Return a positive result, with metadata and verification info DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); @@ -649,7 +713,7 @@ public class PgpDecryptVerify { PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); if (sigList == null) { - // log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_DATA) + log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_INVALID_SIGLIST, 0); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java index 580072957..1a77d96d3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java @@ -435,6 +435,44 @@ public class OperationResultParcel implements Parcelable { MSG_EK_ERROR_DUMMY (R.string.msg_ek_error_dummy), MSG_EK_ERROR_NOT_FOUND (R.string.msg_ek_error_not_found), + // decryptverify + MSG_DC_ASKIP_NO_KEY (R.string.msg_dc_askip_no_key), + MSG_DC_ASKIP_NOT_ALLOWED (R.string.msg_dc_askip_not_allowed), + MSG_DC_ASYM (R.string.msg_dc_asym), + MSG_DC_CLEAR_DATA (R.string.msg_dc_clear_data), + MSG_DC_CLEAR_DECOMPRESS (R.string.msg_dc_clear_decompress), + MSG_DC_CLEAR_META_FILE (R.string.msg_dc_clear_meta_file), + MSG_DC_CLEAR_META_MIME (R.string.msg_dc_clear_meta_mime), + MSG_DC_CLEAR_META_SIZE (R.string.msg_dc_clear_meta_size), + MSG_DC_CLEAR_META_TIME (R.string.msg_dc_clear_meta_time), + MSG_DC_CLEAR (R.string.msg_dc_clear), + MSG_DC_CLEAR_SIGNATURE_BAD (R.string.msg_dc_clear_signature_bad), + MSG_DC_CLEAR_SIGNATURE_CHECK (R.string.msg_dc_clear_signature_check), + MSG_DC_CLEAR_SIGNATURE_OK (R.string.msg_dc_clear_signature_ok), + MSG_DC_CLEAR_SIGNATURE (R.string.msg_dc_clear_signature), + MSG_DC_ERROR_BAD_PASSPHRASE (R.string.msg_dc_error_bad_passphrase), + MSG_DC_ERROR_EXTRACT_KEY (R.string.msg_dc_error_extract_key), + MSG_DC_ERROR_INTEGRITY_CHECK (R.string.msg_dc_error_integrity_check), + MSG_DC_ERROR_INVALID_SIGLIST(R.string.msg_dc_error_invalid_siglist), + MSG_DC_ERROR_IO (R.string.msg_dc_error_io), + MSG_DC_ERROR_NO_DATA (R.string.msg_dc_error_no_data), + MSG_DC_ERROR_NO_KEY (R.string.msg_dc_error_no_key), + MSG_DC_ERROR_PGP_EXCEPTION (R.string.msg_dc_error_pgp_exception), + MSG_DC_INTEGRITY_CHECK_OK (R.string.msg_dc_integrity_check_ok), + MSG_DC_OK_META_ONLY (R.string.msg_dc_ok_meta_only), + MSG_DC_OK (R.string.msg_dc_ok), + MSG_DC_PASS_CACHED (R.string.msg_dc_pass_cached), + MSG_DC_PENDING_NFC (R.string.msg_dc_pending_nfc), + MSG_DC_PENDING_PASSPHRASE (R.string.msg_dc_pending_passphrase), + MSG_DC_PREP_STREAMS (R.string.msg_dc_prep_streams), + MSG_DC (R.string.msg_dc), + MSG_DC_SYM (R.string.msg_dc_sym), + MSG_DC_SYM_SKIP (R.string.msg_dc_sym_skip), + MSG_DC_TRAIL_ASYM (R.string.msg_dc_trail_asym), + MSG_DC_TRAIL_SYM (R.string.msg_dc_trail_sym), + MSG_DC_TRAIL_UNKNOWN (R.string.msg_dc_trail_unknown), + MSG_DC_UNLOCKING (R.string.msg_dc_unlocking), + ; private final int mMsgId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 75e38d5c6..a7a630be1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -156,7 +156,7 @@ public class DecryptMessageFragment extends DecryptFragment { return; } // error, we can't work with this! - result.createNotify(getActivity()); + result.createNotify(getActivity()).show(); return; } @@ -165,7 +165,7 @@ public class DecryptMessageFragment extends DecryptFragment { mMessage.setText(new String(decryptedMessage)); mMessage.setHorizontallyScrolling(false); - result.createNotify(getActivity()); + result.createNotify(getActivity()).show(); // display signature result in activity onResult(result); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index a450b36f8..4e23f36b0 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -764,6 +764,44 @@ "Cannot edit keyring with stripped master key!" "Key not found!" + + "Data not encrypted with known key, skipping…" + "Data not encrypted with allowed key, skipping…" + "Found block of asymmetrically encrypted data" + "Processing literal data" + "Unpacking compressed data" + "Filesize: %s" + "MIME type: %s" + "Filesize: %s" + "Modification time: %s" + "Signature check NOT OK!" + "Verifying signature data" + "Signature check OK" + "Saving signature data for later" + "Processing cleartext data" + "Error unlocking key, bad passphrase!" + "Unknown error unlocking key!" + "Integrity check error!" + "No valid signature data found!" + "Encountered IO Exception during operation!" + "No encrypted data found in stream!" + "No encrypted data with known secret key found in stream!" + "Encountered PGP Exception during operation!" + "Integrity check ok!" + "Only metadata was requested, skipping decryption" + "OK" + "Using passphrase from cache" + "NFC token required, requesting user input…" + "Passphrase required, requesting user input…" + "Preparing streams for decryption" + "Starting decrypt operation…" + "Symmetric data not allowed, skipping…" + "Found block of symmetrically encrypted data" + "Encountered trailing, asymmetrically encrypted data" + "Encountered trailing, symmetrically encrypted data" + "Encountered trailing data of unknown type" + "Unlocking secret key" + "Click to clear cached passphrases" "OpenKeychain has cached %d passphrases" From 7b08b18d251d4d3df681ea3be2235338c6a07c65 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 13 Sep 2014 21:21:48 +0200 Subject: [PATCH 4/4] some DecryptVerify log refinements --- .../keychain/pgp/PgpDecryptVerify.java | 18 +++++++++++++----- OpenKeychain/src/main/res/values/strings.xml | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 769a48a8e..bfa504bfd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -64,6 +64,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URLConnection; import java.security.SignatureException; +import java.util.Date; import java.util.Iterator; import java.util.Set; @@ -403,7 +404,7 @@ public class PgpDecryptVerify { updateProgress(R.string.progress_extracting_key, currentProgress, 100); try { - log.add(LogLevel.WARN, LogType.MSG_DC_UNLOCKING, indent +1); + log.add(LogLevel.INFO, LogType.MSG_DC_UNLOCKING, indent +1); if (!secretEncryptionKey.unlock(mPassphrase)) { log.add(LogLevel.ERROR, LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent +1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); @@ -554,10 +555,17 @@ public class PgpDecryptVerify { literalData.getModificationTime().getTime(), originalSize); - log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_FILE, indent +1); - log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_MIME, indent +1); - log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_TIME, indent +1); - log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_SIZE, indent +1); + if ( ! originalFilename.equals("")) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename); + } + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_MIME, indent +1, + mimeType); + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_TIME, indent +1, + new Date(literalData.getModificationTime().getTime()).toString()); + if (originalSize != 0) { + log.add(LogLevel.DEBUG, LogType.MSG_DC_CLEAR_META_SIZE, indent + 1, + Long.toString(originalSize)); + } // return here if we want to decrypt the metadata only if (mDecryptMetadataOnly) { diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 4e23f36b0..378d68c21 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -767,10 +767,10 @@ "Data not encrypted with known key, skipping…" "Data not encrypted with allowed key, skipping…" - "Found block of asymmetrically encrypted data" + "Found block of asymmetrically encrypted data for key %s" "Processing literal data" "Unpacking compressed data" - "Filesize: %s" + "Filename: %s" "MIME type: %s" "Filesize: %s" "Modification time: %s"