From f0e159a372174db4d0939f8f747a05b62d9b068d Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 14 Sep 2014 00:33:19 +0200 Subject: [PATCH] add SignEncryptResult parcel (probably break stuff) --- .../keychain/pgp/PgpSignEncrypt.java | 382 +++++++++--------- .../keychain/remote/OpenPgpService.java | 77 ++-- .../service/KeychainIntentService.java | 14 +- .../results/OperationResultParcel.java | 31 ++ .../keychain/ui/EncryptFileActivity.java | 2 +- .../keychain/ui/EncryptTextActivity.java | 19 +- OpenKeychain/src/main/res/values/strings.xml | 26 +- 7 files changed, 319 insertions(+), 232 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 070239a80..9f97ac4c9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -35,6 +35,10 @@ 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.OperationResultParcel.LogLevel; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogType; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.OperationLog; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -45,8 +49,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.SignatureException; import java.util.Arrays; import java.util.Date; @@ -247,44 +249,16 @@ public class PgpSignEncrypt { } } - public static class KeyExtractionException extends Exception { - public KeyExtractionException() { - } - } - - public static class NoPassphraseException extends Exception { - public NoPassphraseException() { - } - } - - public static class WrongPassphraseException extends Exception { - public WrongPassphraseException() { - } - } - - public static class NoSigningKeyException extends Exception { - public NoSigningKeyException() { - } - } - - public static class NeedNfcDataException extends Exception { - public byte[] mHashToSign; - public int mHashAlgo; - public Date mCreationTimestamp; - - public NeedNfcDataException(byte[] hashToSign, int hashAlgo, Date creationTimestamp) { - mHashToSign = hashToSign; - mHashAlgo = hashAlgo; - mCreationTimestamp = creationTimestamp; - } - } - /** * Signs and/or encrypts data based on parameters of class */ - public void execute() - throws IOException, PGPException, NoSuchProviderException, - NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException, NeedNfcDataException, WrongPassphraseException { + public SignEncryptResult execute() { + + int indent = 0; + OperationLog log = new OperationLog(); + + log.add(LogLevel.START, LogType.MSG_SE, indent); + indent += 1; boolean enableSignature = mSignatureMasterKeyId != Constants.key.none; boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0) @@ -320,7 +294,8 @@ public class PgpSignEncrypt { // If we weren't handed a passphrase, throw early if (mSignaturePassphrase == null) { - throw new NoPassphraseException(); + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_NO_PASSPHRASE, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } try { @@ -332,22 +307,26 @@ public class PgpSignEncrypt { signingKey = signingKeyRing.getSecretKey(signKeyId); // make sure it's a signing key alright! } catch (ProviderHelper.NotFoundException e) { - throw new NoSigningKeyException(); + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_SIGN_KEY, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } // Make sure we are allowed to sign here! - if ( ! signingKey.canSign()) { - throw new NoSigningKeyException(); + if (!signingKey.canSign()) { + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_KEY_SIGN, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } updateProgress(R.string.progress_extracting_signature_key, 0, 100); try { - if ( ! signingKey.unlock(mSignaturePassphrase)) { - throw new WrongPassphraseException(); + if (!signingKey.unlock(mSignaturePassphrase)) { + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_BAD_PASSPHRASE, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } } catch (PgpGeneralException e) { - throw new KeyExtractionException(); + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_UNLOCK, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } // check if hash algo is supported @@ -372,12 +351,14 @@ public class PgpSignEncrypt { if (mSymmetricPassphrase != null) { // Symmetric encryption - Log.d(Constants.TAG, "encryptionMasterKeyIds length is 0 -> symmetric encryption"); + log.add(LogLevel.DEBUG, LogType.MSG_SE_SYMMETRIC, indent); JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator(mSymmetricPassphrase.toCharArray()); cPk.addMethod(symmetricEncryptionGenerator); } else { + log.add(LogLevel.INFO, LogType.MSG_SE_ASYMMETRIC, indent); + // Asymmetric encryption for (long id : mEncryptionMasterKeyIds) { try { @@ -385,10 +366,14 @@ public class PgpSignEncrypt { KeyRings.buildUnifiedKeyRingUri(id)); CanonicalizedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); + log.add(LogLevel.DEBUG, LogType.MSG_SE_KEY_OK, indent +1, + PgpKeyHelper.convertKeyIdToHex(id)); } catch (PgpGeneralException e) { - Log.e(Constants.TAG, "key not found!", e); + log.add(LogLevel.WARN, LogType.MSG_SE_KEY_WARN, indent +1, + PgpKeyHelper.convertKeyIdToHex(id)); } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); + log.add(LogLevel.WARN, LogType.MSG_SE_KEY_UNKNOWN, indent +1, + PgpKeyHelper.convertKeyIdToHex(id)); } } } @@ -404,168 +389,199 @@ public class PgpSignEncrypt { signatureGenerator = signingKey.getSignatureGenerator( mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp); } catch (PgpGeneralException e) { - // TODO throw correct type of exception (which shouldn't be PGPException) - throw new KeyExtractionException(); + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_NFC, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } } ProgressScaler progressScaler = new ProgressScaler(mProgressable, 8, 95, 100); PGPCompressedDataGenerator compressGen = null; - OutputStream pOut = null; + OutputStream pOut; OutputStream encryptionOut = null; BCPGOutputStream bcpgOut; - if (enableEncryption) { - /* actual encryption */ - updateProgress(R.string.progress_encrypting, 8, 100); + try { - encryptionOut = cPk.open(out, new byte[1 << 16]); + if (enableEncryption) { + /* actual encryption */ + updateProgress(R.string.progress_encrypting, 8, 100); + log.add(LogLevel.DEBUG, enableSignature + ? LogType.MSG_SE_SIGCRYPTING + : LogType.MSG_SE_ENCRYPTING, + indent); + indent += 1; - if (enableCompression) { - compressGen = new PGPCompressedDataGenerator(mCompressionId); - bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); + encryptionOut = cPk.open(out, new byte[1 << 16]); + + if (enableCompression) { + log.add(LogLevel.DEBUG, LogType.MSG_SE_COMPRESSING, indent); + compressGen = new PGPCompressedDataGenerator(mCompressionId); + bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); + } else { + bcpgOut = new BCPGOutputStream(encryptionOut); + } + + if (enableSignature) { + signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); + } + + PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); + char literalDataFormatTag; + if (mCleartextInput) { + literalDataFormatTag = PGPLiteralData.UTF8; + } else { + literalDataFormatTag = PGPLiteralData.BINARY; + } + pOut = literalGen.open(bcpgOut, literalDataFormatTag, mOriginalFilename, new Date(), + new byte[1 << 16]); + + long alreadyWritten = 0; + int length; + byte[] buffer = new byte[1 << 16]; + InputStream in = mData.getInputStream(); + while ((length = in.read(buffer)) > 0) { + pOut.write(buffer, 0, length); + + // update signature buffer if signature is requested + if (enableSignature) { + signatureGenerator.update(buffer, 0, length); + } + + alreadyWritten += length; + if (mData.getSize() > 0) { + long progress = 100 * alreadyWritten / mData.getSize(); + progressScaler.setProgress((int) progress, 100); + } + } + + literalGen.close(); + indent -= 1; + + } else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) { + /* cleartext signature: sign-only of ascii text */ + + updateProgress(R.string.progress_signing, 8, 100); + log.add(LogLevel.DEBUG, LogType.MSG_SE_SIGNING, indent); + + // write -----BEGIN PGP SIGNED MESSAGE----- + armorOut.beginClearText(mSignatureHashAlgorithm); + + InputStream in = mData.getInputStream(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + + // update signature buffer with first line + processLine(reader.readLine(), armorOut, signatureGenerator); + + // TODO: progress: fake annealing? + while (true) { + String line = reader.readLine(); + + // end cleartext signature with newline, see http://tools.ietf.org/html/rfc4880#section-7 + if (line == null) { + armorOut.write(NEW_LINE); + break; + } + + armorOut.write(NEW_LINE); + + // update signature buffer with input line + signatureGenerator.update(NEW_LINE); + processLine(line, armorOut, signatureGenerator); + } + + armorOut.endClearText(); + + pOut = new BCPGOutputStream(armorOut); + } else if (enableSignature && !mCleartextInput) { + /* sign-only binary (files/data stream) */ + + updateProgress(R.string.progress_signing, 8, 100); + log.add(LogLevel.DEBUG, LogType.MSG_SE_ENCRYPTING, indent); + + InputStream in = mData.getInputStream(); + + if (enableCompression) { + compressGen = new PGPCompressedDataGenerator(mCompressionId); + bcpgOut = new BCPGOutputStream(compressGen.open(out)); + } else { + bcpgOut = new BCPGOutputStream(out); + } + + signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); + + PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); + pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), + new byte[1 << 16]); + + long alreadyWritten = 0; + int length; + byte[] buffer = new byte[1 << 16]; + while ((length = in.read(buffer)) > 0) { + pOut.write(buffer, 0, length); + + signatureGenerator.update(buffer, 0, length); + + alreadyWritten += length; + if (mData.getSize() > 0) { + long progress = 100 * alreadyWritten / mData.getSize(); + progressScaler.setProgress((int) progress, 100); + } + } + + literalGen.close(); } else { - bcpgOut = new BCPGOutputStream(encryptionOut); + pOut = null; + log.add(LogLevel.WARN, LogType.MSG_SE_CLEARSIGN_ONLY, indent); } if (enableSignature) { - signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); - } - - PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); - char literalDataFormatTag; - if (mCleartextInput) { - literalDataFormatTag = PGPLiteralData.UTF8; - } else { - literalDataFormatTag = PGPLiteralData.BINARY; - } - pOut = literalGen.open(bcpgOut, literalDataFormatTag, mOriginalFilename, new Date(), - new byte[1 << 16]); - - long alreadyWritten = 0; - int length; - byte[] buffer = new byte[1 << 16]; - InputStream in = mData.getInputStream(); - while ((length = in.read(buffer)) > 0) { - pOut.write(buffer, 0, length); - - // update signature buffer if signature is requested - if (enableSignature) { - signatureGenerator.update(buffer, 0, length); - } - - alreadyWritten += length; - if (mData.getSize() > 0) { - long progress = 100 * alreadyWritten / mData.getSize(); - progressScaler.setProgress((int) progress, 100); + updateProgress(R.string.progress_generating_signature, 95, 100); + try { + signatureGenerator.generate().encode(pOut); + } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) { + // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed + log.add(LogLevel.OK, LogType.MSG_SE_PENDING_NFC, indent); + SignEncryptResult result = + new SignEncryptResult(SignEncryptResult.RESULT_PENDING_NFC, log); + result.setNfcData(e.hashToSign, e.hashAlgo, e.creationTimestamp); + return new SignEncryptResult(SignEncryptResult.RESULT_PENDING_NFC, log); } } - literalGen.close(); - } else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) { - /* cleartext signature: sign-only of ascii text */ - - updateProgress(R.string.progress_signing, 8, 100); - - // write -----BEGIN PGP SIGNED MESSAGE----- - armorOut.beginClearText(mSignatureHashAlgorithm); - - InputStream in = mData.getInputStream(); - final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - - // update signature buffer with first line - processLine(reader.readLine(), armorOut, signatureGenerator); - - // TODO: progress: fake annealing? - while (true) { - String line = reader.readLine(); - - // end cleartext signature with newline, see http://tools.ietf.org/html/rfc4880#section-7 - if (line == null) { - armorOut.write(NEW_LINE); - break; + // closing outputs + // NOTE: closing needs to be done in the correct order! + // TODO: closing bcpgOut and pOut??? + if (enableEncryption) { + if (enableCompression) { + compressGen.close(); } - armorOut.write(NEW_LINE); - - // update signature buffer with input line - signatureGenerator.update(NEW_LINE); - processLine(line, armorOut, signatureGenerator); + encryptionOut.close(); + } + if (mEnableAsciiArmorOutput) { + armorOut.close(); } - armorOut.endClearText(); + out.close(); + mOutStream.close(); - pOut = new BCPGOutputStream(armorOut); - } else if (enableSignature && !mCleartextInput) { - /* sign-only binary (files/data stream) */ - - updateProgress(R.string.progress_signing, 8, 100); - - InputStream in = mData.getInputStream(); - - if (enableCompression) { - compressGen = new PGPCompressedDataGenerator(mCompressionId); - bcpgOut = new BCPGOutputStream(compressGen.open(out)); - } else { - bcpgOut = new BCPGOutputStream(out); - } - - signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); - - PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); - pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), - new byte[1 << 16]); - - long alreadyWritten = 0; - int length; - byte[] buffer = new byte[1 << 16]; - while ((length = in.read(buffer)) > 0) { - pOut.write(buffer, 0, length); - - signatureGenerator.update(buffer, 0, length); - - alreadyWritten += length; - if (mData.getSize() > 0) { - long progress = 100 * alreadyWritten / mData.getSize(); - progressScaler.setProgress((int) progress, 100); - } - } - - literalGen.close(); - } else { - pOut = null; - Log.e(Constants.TAG, "not supported!"); + } catch (SignatureException e) { + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_SIG, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + } catch (PGPException e) { + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_PGP, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + } catch (IOException e) { + log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_IO, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); } - if (enableSignature) { - updateProgress(R.string.progress_generating_signature, 95, 100); - try { - signatureGenerator.generate().encode(pOut); - } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) { - // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed - throw new NeedNfcDataException(e.hashToSign, e.hashAlgo, e.creationTimestamp); - } - } - - // closing outputs - // NOTE: closing needs to be done in the correct order! - // TODO: closing bcpgOut and pOut??? - if (enableEncryption) { - if (enableCompression) { - compressGen.close(); - } - - encryptionOut.close(); - } - if (mEnableAsciiArmorOutput) { - armorOut.close(); - } - - out.close(); - mOutStream.close(); - updateProgress(R.string.progress_done, 100, 100); + + log.add(LogLevel.OK, LogType.MSG_SE_OK, indent); + return new SignEncryptResult(SignEncryptResult.RESULT_OK, log); + } private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput, 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 205395dbf..29f888a82 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -45,6 +45,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity; import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogEntryParcel; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.ui.ImportKeysActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.util.InputData; @@ -269,25 +271,28 @@ public class OpenPgpService extends RemoteService { // TODO: currently always assume cleartext input, no sign-only of binary currently! builder.setCleartextInput(true); - try { - builder.build().execute(); + // execute PGP operation! + SignEncryptResult result = builder.build().execute(); - // throw exceptions upwards to client with meaningful messages - } catch (PgpSignEncrypt.KeyExtractionException e) { - throw new Exception(getString(R.string.error_could_not_extract_private_key)); - } catch (PgpSignEncrypt.NoPassphraseException e) { - throw new Exception(getString(R.string.error_no_signature_passphrase)); - } catch (PgpSignEncrypt.WrongPassphraseException e) { - throw new Exception(getString(R.string.error_wrong_passphrase)); - } catch (PgpSignEncrypt.NoSigningKeyException e) { - throw new Exception(getString(R.string.error_no_signature_key)); - } catch (PgpSignEncrypt.NeedNfcDataException e) { - // return PendingIntent to execute NFC activity - // pass through the signature creation timestamp to be used again on second execution - // of PgpSignEncrypt when we have the signed hash! - data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, e.mCreationTimestamp.getTime()); - return getNfcSignIntent(data, passphrase, e.mHashToSign, e.mHashAlgo); + if (result.isPending()) { + switch (result.getResult()) { + case SignEncryptResult.RESULT_PENDING_NFC: + // return PendingIntent to execute NFC activity + // pass through the signature creation timestamp to be used again on second execution + // of PgpSignEncrypt when we have the signed hash! + data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime()); + return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo()); + + default: + throw new Exception("Encountered unhandled pending state - please file a bug report!"); + } } + + if (!result.success()) { + LogEntryParcel errorMsg = result.getLog().getLast(); + throw new Exception(getString(errorMsg.mType.getMsgId())); + } + } finally { is.close(); os.close(); @@ -379,26 +384,28 @@ public class OpenPgpService extends RemoteService { .setNfcState(nfcSignedHash, nfcCreationDate); } - try { - // execute PGP operation! - builder.build().execute(); + // execute PGP operation! + SignEncryptResult result = builder.build().execute(); - // throw exceptions upwards to client with meaningful messages - } catch (PgpSignEncrypt.KeyExtractionException e) { - throw new Exception(getString(R.string.error_could_not_extract_private_key)); - } catch (PgpSignEncrypt.NoPassphraseException e) { - throw new Exception(getString(R.string.error_no_signature_passphrase)); - } catch (PgpSignEncrypt.WrongPassphraseException e) { - throw new Exception(getString(R.string.error_wrong_passphrase)); - } catch (PgpSignEncrypt.NoSigningKeyException e) { - throw new Exception(getString(R.string.error_no_signature_key)); - } catch (PgpSignEncrypt.NeedNfcDataException e) { - // return PendingIntent to execute NFC activity - // pass through the signature creation timestamp to be used again on second execution - // of PgpSignEncrypt when we have the signed hash! - data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, e.mCreationTimestamp.getTime()); - return getNfcSignIntent(data, passphrase, e.mHashToSign, e.mHashAlgo); + if (result.isPending()) { + switch (result.getResult()) { + case SignEncryptResult.RESULT_PENDING_NFC: + // return PendingIntent to execute NFC activity + // pass through the signature creation timestamp to be used again on second execution + // of PgpSignEncrypt when we have the signed hash! + data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime()); + return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo()); + + default: + throw new Exception("Encountered unhandled pending state - please file a bug report!"); + } } + + if (!result.success()) { + LogEntryParcel errorMsg = result.getLog().getLast(); + throw new Exception(getString(errorMsg.mType.getMsgId())); + } + } finally { is.close(); os.close(); 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 f8ef9b0f6..e09c71787 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -63,6 +63,7 @@ import org.sufficientlysecure.keychain.service.results.ConsolidateResult; import org.sufficientlysecure.keychain.service.results.EditKeyResult; import org.sufficientlysecure.keychain.service.results.ImportKeyResult; import org.sufficientlysecure.keychain.service.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -91,7 +92,7 @@ public class KeychainIntentService extends IntentService implements Progressable public static final String EXTRA_DATA = "data"; /* possible actions */ - public static final String ACTION_ENCRYPT_SIGN = Constants.INTENT_PREFIX + "ENCRYPT_SIGN"; + public static final String ACTION_SIGN_ENCRYPT = Constants.INTENT_PREFIX + "SIGN_ENCRYPT"; public static final String ACTION_DECRYPT_VERIFY = Constants.INTENT_PREFIX + "DECRYPT_VERIFY"; @@ -247,7 +248,7 @@ public class KeychainIntentService extends IntentService implements Progressable String action = intent.getAction(); // executeServiceMethod action from extra bundle - if (ACTION_ENCRYPT_SIGN.equals(action)) { + if (ACTION_SIGN_ENCRYPT.equals(action)) { try { /* Input */ int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET); @@ -309,7 +310,8 @@ public class KeychainIntentService extends IntentService implements Progressable builder.setCleartextInput(true); } - builder.build().execute(); + SignEncryptResult result = builder.build().execute(); + resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result); outStream.close(); @@ -779,12 +781,6 @@ public class KeychainIntentService extends IntentService implements Progressable if (e instanceof PgpGeneralMsgIdException) { e = ((PgpGeneralMsgIdException) e).getContextualized(this); message = e.getMessage(); - } else if (e instanceof PgpSignEncrypt.KeyExtractionException) { - message = getString(R.string.error_could_not_extract_private_key); - } else if (e instanceof PgpSignEncrypt.NoPassphraseException) { - message = getString(R.string.error_no_signature_passphrase); - } else if (e instanceof PgpSignEncrypt.NoSigningKeyException) { - message = getString(R.string.error_no_signature_key); } else { message = e.getMessage(); } 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 46823a24d..56f5248cb 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 @@ -474,6 +474,30 @@ public class OperationResultParcel implements Parcelable { MSG_DC_TRAIL_UNKNOWN (R.string.msg_dc_trail_unknown), MSG_DC_UNLOCKING (R.string.msg_dc_unlocking), + // signencrypt + MSG_SE_ASYMMETRIC (R.string.msg_se_asymmetric), + MSG_SE_CLEARSIGN_ONLY (R.string.msg_se_clearsign_only), + MSG_SE_COMPRESSING (R.string.msg_se_compressing), + MSG_SE_ENCRYPTING (R.string.msg_se_encrypting), + MSG_SE_ERROR_BAD_PASSPHRASE (R.string.msg_se_error_bad_passphrase), + MSG_SE_ERROR_IO (R.string.msg_se_error_io), + MSG_SE_ERROR_SIGN_KEY(R.string.msg_se_error_sign_key), + MSG_SE_ERROR_KEY_SIGN (R.string.msg_se_error_key_sign), + MSG_SE_ERROR_NFC (R.string.msg_se_error_nfc), + MSG_SE_ERROR_NO_PASSPHRASE (R.string.msg_se_error_no_passphrase), + MSG_SE_ERROR_PGP (R.string.msg_se_error_pgp), + MSG_SE_ERROR_SIG (R.string.msg_se_error_sig), + MSG_SE_ERROR_UNLOCK (R.string.msg_se_error_unlock), + MSG_SE_KEY_OK (R.string.msg_se_key_ok), + MSG_SE_KEY_UNKNOWN (R.string.msg_se_key_unknown), + MSG_SE_KEY_WARN (R.string.msg_se_key_warn), + MSG_SE_OK (R.string.msg_se_ok), + MSG_SE_PENDING_NFC (R.string.msg_se_pending_nfc), + MSG_SE (R.string.msg_se), + MSG_SE_SIGNING (R.string.msg_se_signing), + MSG_SE_SIGCRYPTING (R.string.msg_se_sigcrypting), + MSG_SE_SYMMETRIC (R.string.msg_se_symmetric), + ; private final int mMsgId; @@ -562,6 +586,13 @@ public class OperationResultParcel implements Parcelable { return mParcels.isEmpty(); } + public LogEntryParcel getLast() { + if (mParcels.isEmpty()) { + return null; + } + return mParcels.get(mParcels.size() -1); + } + @Override public Iterator iterator() { return mParcels.iterator(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java index 96f8bd983..a5de20986 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java @@ -183,7 +183,7 @@ public class EncryptFileActivity extends DrawerActivity implements EncryptActivi // Send all information needed to service to edit key in other thread Intent intent = new Intent(this, KeychainIntentService.class); - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); + intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT); intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle()); // Message is received after encrypting is done in KeychainIntentService diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 6e6e52562..4bf1cad3c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -184,7 +185,7 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi // Send all information needed to service to edit key in other thread Intent intent = new Intent(this, KeychainIntentService.class); - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); + intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT); intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle()); // Message is received after encrypting is done in KeychainIntentService @@ -195,14 +196,26 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + + SignEncryptResult result = + message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); + + // TODO if (result.isPending()) + + if (!result.success()) { + result.createNotify(EncryptTextActivity.this).show(); + return; + } + if (mShareAfterEncrypt) { // Share encrypted message/file startActivity(sendWithChooserExcludingEncrypt(message)); } else { // Copy to clipboard copyToClipboard(message); - Notify.showNotify(EncryptTextActivity.this, - R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); + result.createNotify(EncryptTextActivity.this).show(); + // Notify.showNotify(EncryptTextActivity.this, + // R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); } } } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 62299ed34..e1fcf4a0b 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -701,7 +701,7 @@ "Revoked user ids cannot be primary!" "Expiry time cannot be "same as before" on subkey creation. This is a programming error, please file a bug report!" "Fatal error decrypting master key! This is likely a programming error, please file a bug report!" - "PGP internal exception!" + "Internal PGP error!" "Signature exception!" "Modifying master certifications" "Changing passphrase for keyring…" @@ -803,6 +803,30 @@ "Encountered trailing data of unknown type" "Unlocking secret key" + + "Preparing public keys for encryption" + "Signing of cleartext input not supported!" + "Preparing compression" + "Encrypting data" + "Bad passphrase!" + "Encountered IO Exception during operation!" + "Selected signing key cannot sign data!" + "Error fetching signing key!" + "NFC data error!" + "No passphrase provided!" + "Internal PGP error!" + "Encountered PGP signature exception!" + "Unknown error unlocking key!" + "Encrypting for key: %s" + "Missing key for encryption: %s" + "Bad key for encryption: %s" + "Sign/Encrypt operation successful!" + "NFC token required, requesting user input…" + "Signing data (without encryption)" + "Encrypting data with signature" + "Starting sign and/or encrypt operation" + "Preparing symmetric encryption" + "Click to clear cached passphrases" "OpenKeychain has cached %d passphrases"