rewrite PgpDecryptVerify input, introduce PgpDecryptVerifyInputParcel

This commit is contained in:
Vincent Breitmoser 2015-05-30 13:25:47 +02:00
parent 36ecd60c1b
commit 0d8370be1d
10 changed files with 331 additions and 350 deletions

View file

@ -36,6 +36,23 @@ public class DecryptVerifyResult extends InputPendingResult {
// https://tools.ietf.org/html/rfc4880#page56 // https://tools.ietf.org/html/rfc4880#page56
String mCharset; String mCharset;
byte[] mOutputBytes;
public DecryptVerifyResult(int result, OperationLog log) {
super(result, log);
}
public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput) {
super(log, requiredInput);
}
public DecryptVerifyResult(Parcel source) {
super(source);
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
}
public boolean isKeysDisallowed () { public boolean isKeysDisallowed () {
return (mResult & RESULT_KEY_DISALLOWED) == RESULT_KEY_DISALLOWED; return (mResult & RESULT_KEY_DISALLOWED) == RESULT_KEY_DISALLOWED;
} }
@ -64,18 +81,12 @@ public class DecryptVerifyResult extends InputPendingResult {
mCharset = charset; mCharset = charset;
} }
public DecryptVerifyResult(int result, OperationLog log) { public void setOutputBytes(byte[] outputBytes) {
super(result, log); mOutputBytes = outputBytes;
} }
public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput) { public byte[] getOutputBytes() {
super(log, requiredInput); return mOutputBytes;
}
public DecryptVerifyResult(Parcel source) {
super(source);
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
} }
public int describeContents() { public int describeContents() {

View file

@ -58,6 +58,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Passphrase;
@ -66,6 +67,7 @@ import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -73,147 +75,90 @@ import java.net.URLConnection;
import java.security.SignatureException; import java.security.SignatureException;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set;
/** /**
* This class uses a Builder pattern! * This class uses a Builder pattern!
*/ */
public class PgpDecryptVerify extends BaseOperation { public class PgpDecryptVerify extends BaseOperation {
private InputData mData; public PgpDecryptVerify(Context context, ProviderHelper providerHelper, Progressable progressable) {
private OutputStream mOutStream; super(context, providerHelper, progressable);
private boolean mAllowSymmetricDecryption;
private Set<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDetachedSignature;
private String mRequiredSignerFingerprint;
private boolean mSignedLiteralData;
protected PgpDecryptVerify(Builder builder) {
super(builder.mContext, builder.mProviderHelper, builder.mProgressable);
// private Constructor can only be called from Builder
this.mData = builder.mData;
this.mOutStream = builder.mOutStream;
this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption;
this.mAllowedKeyIds = builder.mAllowedKeyIds;
this.mDecryptMetadataOnly = builder.mDecryptMetadataOnly;
this.mDetachedSignature = builder.mDetachedSignature;
this.mSignedLiteralData = builder.mSignedLiteralData;
this.mRequiredSignerFingerprint = builder.mRequiredSignerFingerprint;
}
public static class Builder {
// mandatory parameter
private Context mContext;
private ProviderHelper mProviderHelper;
private InputData mData;
// optional
private OutputStream mOutStream = null;
private Progressable mProgressable = null;
private boolean mAllowSymmetricDecryption = true;
private Set<Long> mAllowedKeyIds = null;
private boolean mDecryptMetadataOnly = false;
private byte[] mDetachedSignature = null;
private String mRequiredSignerFingerprint = null;
private boolean mSignedLiteralData = false;
public Builder(Context context, ProviderHelper providerHelper,
Progressable progressable,
InputData data, OutputStream outStream) {
mContext = context;
mProviderHelper = providerHelper;
mProgressable = progressable;
mData = data;
mOutStream = outStream;
}
/**
* This is used when verifying signed literals to check that they are signed with
* the required key
*/
public Builder setRequiredSignerFingerprint(String fingerprint) {
mRequiredSignerFingerprint = fingerprint;
return this;
}
/**
* This is to force a mode where the message is just the signature key id and
* then a literal data packet; used in Keybase.io proofs
*/
public Builder setSignedLiteralData(boolean signedLiteralData) {
mSignedLiteralData = signedLiteralData;
return this;
}
public Builder setAllowSymmetricDecryption(boolean allowSymmetricDecryption) {
mAllowSymmetricDecryption = allowSymmetricDecryption;
return this;
}
/**
* Allow these key ids alone for decryption.
* This means only ciphertexts encrypted for one of these private key can be decrypted.
*/
public Builder setAllowedKeyIds(Set<Long> allowedKeyIds) {
mAllowedKeyIds = allowedKeyIds;
return this;
}
/**
* If enabled, the actual decryption/verification of the content will not be executed.
* The metadata only will be decrypted and returned.
*/
public Builder setDecryptMetadataOnly(boolean decryptMetadataOnly) {
mDecryptMetadataOnly = decryptMetadataOnly;
return this;
}
/**
* If detachedSignature != null, it will be used exclusively to verify the signature
*/
public Builder setDetachedSignature(byte[] detachedSignature) {
mDetachedSignature = detachedSignature;
return this;
}
public PgpDecryptVerify build() {
return new PgpDecryptVerify(this);
}
} }
/** /**
* Decrypts and/or verifies data based on parameters of class * Decrypts and/or verifies data based on parameters of class
*/ */
public DecryptVerifyResult execute(CryptoInputParcel cryptoInput) { public DecryptVerifyResult execute(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput) {
InputData inputData;
OutputStream outputStream;
if (input.getInputBytes() != null) {
byte[] inputBytes = input.getInputBytes();
inputData = new InputData(new ByteArrayInputStream(inputBytes), inputBytes.length);
} else {
try {
InputStream inputStream = mContext.getContentResolver().openInputStream(input.getInputUri());
long inputSize = FileHelper.getFileSize(mContext, input.getInputUri(), 0);
inputData = new InputData(inputStream, inputSize);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
if (input.getOutputUri() == null) {
outputStream = new ByteArrayOutputStream();
} else {
try {
outputStream = mContext.getContentResolver().openOutputStream(input.getOutputUri());
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
DecryptVerifyResult result = executeInternal(input, cryptoInput, inputData, outputStream);
if (outputStream instanceof ByteArrayOutputStream) {
byte[] outputData = ((ByteArrayOutputStream) outputStream).toByteArray();
result.setOutputBytes(outputData);
}
return result;
}
public DecryptVerifyResult execute(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
return executeInternal(input, cryptoInput, inputData, outputStream);
}
private DecryptVerifyResult executeInternal(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
try { try {
if (mDetachedSignature != null) { if (input.getDetachedSignature() != null) {
Log.d(Constants.TAG, "Detached signature present, verifying with this signature only"); Log.d(Constants.TAG, "Detached signature present, verifying with this signature only");
return verifyDetachedSignature(mData.getInputStream(), 0); return verifyDetachedSignature(input, inputData, outputStream, 0);
} else { } else {
// automatically works with PGP ascii armor and PGP binary // automatically works with PGP ascii armor and PGP binary
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream()); InputStream in = PGPUtil.getDecoderStream(inputData.getInputStream());
if (in instanceof ArmoredInputStream) { if (in instanceof ArmoredInputStream) {
ArmoredInputStream aIn = (ArmoredInputStream) in; ArmoredInputStream aIn = (ArmoredInputStream) in;
// it is ascii armored // it is ascii armored
Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine()); Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine());
if (mSignedLiteralData) { if (input.isSignedLiteralData()) {
return verifySignedLiteralData(aIn, 0); return verifySignedLiteralData(input, aIn, outputStream, 0);
} else if (aIn.isClearText()) { } else if (aIn.isClearText()) {
// a cleartext signature, verify it with the other method // a cleartext signature, verify it with the other method
return verifyCleartextSignature(aIn, 0); return verifyCleartextSignature(aIn, 0);
} else { } else {
// else: ascii armored encryption! go on... // else: ascii armored encryption! go on...
return decryptVerify(cryptoInput, in, 0); return decryptVerify(input, cryptoInput, in, outputStream, 0);
} }
} else { } else {
return decryptVerify(cryptoInput, in, 0); return decryptVerify(input, cryptoInput, in, outputStream, 0);
} }
} }
} catch (PGPException e) { } catch (PGPException e) {
@ -232,7 +177,8 @@ public class PgpDecryptVerify extends BaseOperation {
/** /**
* Verify Keybase.io style signed literal data * Verify Keybase.io style signed literal data
*/ */
private DecryptVerifyResult verifySignedLiteralData(InputStream in, int indent) private DecryptVerifyResult verifySignedLiteralData(
PgpDecryptVerifyInputParcel input, InputStream in, OutputStream out, int indent)
throws IOException, PGPException { throws IOException, PGPException {
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
log.add(LogType.MSG_VL, indent); log.add(LogType.MSG_VL, indent);
@ -283,9 +229,9 @@ public class PgpDecryptVerify extends BaseOperation {
} }
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(signingRing.getFingerprint()); String fingerprint = KeyFormattingUtils.convertFingerprintToHex(signingRing.getFingerprint());
if (!(mRequiredSignerFingerprint.equals(fingerprint))) { if (!(input.getRequiredSignerFingerprint().equals(fingerprint))) {
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent); log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + mRequiredSignerFingerprint + Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + input.getRequiredSignerFingerprint() +
" got " + fingerprint + "!"); " got " + fingerprint + "!");
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
} }
@ -317,7 +263,7 @@ public class PgpDecryptVerify extends BaseOperation {
int length; int length;
byte[] buffer = new byte[1 << 16]; byte[] buffer = new byte[1 << 16];
while ((length = dataIn.read(buffer)) > 0) { while ((length = dataIn.read(buffer)) > 0) {
mOutStream.write(buffer, 0, length); out.write(buffer, 0, length);
signature.update(buffer, 0, length); signature.update(buffer, 0, length);
} }
@ -363,8 +309,9 @@ public class PgpDecryptVerify extends BaseOperation {
/** /**
* Decrypt and/or verifies binary or ascii armored pgp * Decrypt and/or verifies binary or ascii armored pgp
*/ */
private DecryptVerifyResult decryptVerify(CryptoInputParcel cryptoInput, private DecryptVerifyResult decryptVerify(
InputStream in, int indent) throws IOException, PGPException { PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
InputStream in, OutputStream out, int indent) throws IOException, PGPException {
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
@ -455,13 +402,13 @@ public class PgpDecryptVerify extends BaseOperation {
} }
// allow only specific keys for decryption? // allow only specific keys for decryption?
if (mAllowedKeyIds != null) { if (input.getAllowedKeyIds() != null) {
long masterKeyId = secretKeyRing.getMasterKeyId(); long masterKeyId = secretKeyRing.getMasterKeyId();
Log.d(Constants.TAG, "encData.getKeyID(): " + subKeyId); Log.d(Constants.TAG, "encData.getKeyID(): " + subKeyId);
Log.d(Constants.TAG, "mAllowedKeyIds: " + mAllowedKeyIds); Log.d(Constants.TAG, "mAllowedKeyIds: " + input.getAllowedKeyIds());
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
if (!mAllowedKeyIds.contains(masterKeyId)) { if (!input.getAllowedKeyIds().contains(masterKeyId)) {
// this key is in our db, but NOT allowed! // this key is in our db, but NOT allowed!
// continue with the next packet in the while loop // continue with the next packet in the while loop
skippedDisallowedKey = true; skippedDisallowedKey = true;
@ -515,7 +462,7 @@ public class PgpDecryptVerify extends BaseOperation {
log.add(LogType.MSG_DC_SYM, indent); log.add(LogType.MSG_DC_SYM, indent);
if (!mAllowSymmetricDecryption) { if (!input.isAllowSymmetricDecryption()) {
log.add(LogType.MSG_DC_SYM_SKIP, indent + 1); log.add(LogType.MSG_DC_SYM_SKIP, indent + 1);
continue; continue;
} }
@ -764,7 +711,7 @@ public class PgpDecryptVerify extends BaseOperation {
} }
// return here if we want to decrypt the metadata only // return here if we want to decrypt the metadata only
if (mDecryptMetadataOnly) { if (input.isDecryptMetadataOnly()) {
log.add(LogType.MSG_DC_OK_META_ONLY, indent); log.add(LogType.MSG_DC_OK_META_ONLY, indent);
DecryptVerifyResult result = DecryptVerifyResult result =
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
@ -787,13 +734,13 @@ public class PgpDecryptVerify extends BaseOperation {
InputStream dataIn = literalData.getInputStream(); InputStream dataIn = literalData.getInputStream();
long alreadyWritten = 0; long alreadyWritten = 0;
long wholeSize = mData.getSize() - mData.getStreamPosition(); long wholeSize = 0; // TODO inputData.getSize() - inputData.getStreamPosition();
int length; int length;
byte[] buffer = new byte[1 << 16]; byte[] buffer = new byte[1 << 16];
while ((length = dataIn.read(buffer)) > 0) { while ((length = dataIn.read(buffer)) > 0) {
Log.d(Constants.TAG, "read bytes: " + length); // Log.d(Constants.TAG, "read bytes: " + length);
if (mOutStream != null) { if (out != null) {
mOutStream.write(buffer, 0, length); out.write(buffer, 0, length);
} }
// update signature buffer if signature is also present // update signature buffer if signature is also present
@ -919,8 +866,8 @@ public class PgpDecryptVerify extends BaseOperation {
out.close(); out.close();
byte[] clearText = out.toByteArray(); byte[] clearText = out.toByteArray();
if (mOutStream != null) { if (out != null) {
mOutStream.write(clearText); out.write(clearText);
} }
updateProgress(R.string.progress_processing_signature, 60, 100); updateProgress(R.string.progress_processing_signature, 60, 100);
@ -987,7 +934,8 @@ public class PgpDecryptVerify extends BaseOperation {
return result; return result;
} }
private DecryptVerifyResult verifyDetachedSignature(InputStream in, int indent) private DecryptVerifyResult verifyDetachedSignature(
PgpDecryptVerifyInputParcel input, InputData inputData, OutputStream out, int indent)
throws IOException, PGPException { throws IOException, PGPException {
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
@ -997,7 +945,7 @@ public class PgpDecryptVerify extends BaseOperation {
signatureResultBuilder.setSignatureOnly(true); signatureResultBuilder.setSignatureOnly(true);
updateProgress(R.string.progress_processing_signature, 0, 100); updateProgress(R.string.progress_processing_signature, 0, 100);
InputStream detachedSigIn = new ByteArrayInputStream(mDetachedSignature); InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature());
detachedSigIn = PGPUtil.getDecoderStream(detachedSigIn); detachedSigIn = PGPUtil.getDecoderStream(detachedSigIn);
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(detachedSigIn); JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(detachedSigIn);
@ -1022,12 +970,13 @@ public class PgpDecryptVerify extends BaseOperation {
ProgressScaler progressScaler = new ProgressScaler(mProgressable, 60, 90, 100); ProgressScaler progressScaler = new ProgressScaler(mProgressable, 60, 90, 100);
long alreadyWritten = 0; long alreadyWritten = 0;
long wholeSize = mData.getSize() - mData.getStreamPosition(); long wholeSize = inputData.getSize() - inputData.getStreamPosition();
int length; int length;
byte[] buffer = new byte[1 << 16]; byte[] buffer = new byte[1 << 16];
InputStream in = inputData.getInputStream();
while ((length = in.read(buffer)) > 0) { while ((length = in.read(buffer)) > 0) {
if (mOutStream != null) { if (out != null) {
mOutStream.write(buffer, 0, length); out.write(buffer, 0, length);
} }
// update signature buffer if signature is also present // update signature buffer if signature is also present

View file

@ -0,0 +1,162 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import java.util.HashSet;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
public class PgpDecryptVerifyInputParcel implements Parcelable {
private Uri mInputUri;
private Uri mOutputUri;
private byte[] mInputBytes;
private boolean mAllowSymmetricDecryption;
private HashSet<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDetachedSignature;
private String mRequiredSignerFingerprint;
private boolean mSignedLiteralData;
public PgpDecryptVerifyInputParcel() {
}
public PgpDecryptVerifyInputParcel(Uri inputUri, Uri outputUri) {
mInputUri = inputUri;
mOutputUri = outputUri;
}
public PgpDecryptVerifyInputParcel(byte[] inputBytes) {
mInputBytes = inputBytes;
}
PgpDecryptVerifyInputParcel(Parcel source) {
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mInputUri = source.readParcelable(getClass().getClassLoader());
mOutputUri = source.readParcelable(getClass().getClassLoader());
mInputBytes = source.createByteArray();
mAllowSymmetricDecryption = source.readInt() != 0;
mAllowedKeyIds = (HashSet<Long>) source.readSerializable();
mDecryptMetadataOnly = source.readInt() != 0;
mDetachedSignature = source.createByteArray();
mRequiredSignerFingerprint = source.readString();
mSignedLiteralData = source.readInt() != 0;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mInputUri, 0);
dest.writeParcelable(mOutputUri, 0);
dest.writeByteArray(mInputBytes);
dest.writeInt(mAllowSymmetricDecryption ? 1 : 0);
dest.writeSerializable(mAllowedKeyIds);
dest.writeInt(mDecryptMetadataOnly ? 1 : 0);
dest.writeByteArray(mDetachedSignature);
dest.writeString(mRequiredSignerFingerprint);
dest.writeInt(mSignedLiteralData ? 1 : 0);
}
byte[] getInputBytes() {
return mInputBytes;
}
Uri getInputUri() {
return mInputUri;
}
Uri getOutputUri() {
return mOutputUri;
}
boolean isAllowSymmetricDecryption() {
return mAllowSymmetricDecryption;
}
public PgpDecryptVerifyInputParcel setAllowSymmetricDecryption(boolean allowSymmetricDecryption) {
mAllowSymmetricDecryption = allowSymmetricDecryption;
return this;
}
HashSet<Long> getAllowedKeyIds() {
return mAllowedKeyIds;
}
public PgpDecryptVerifyInputParcel setAllowedKeyIds(HashSet<Long> allowedKeyIds) {
mAllowedKeyIds = allowedKeyIds;
return this;
}
boolean isDecryptMetadataOnly() {
return mDecryptMetadataOnly;
}
public PgpDecryptVerifyInputParcel setDecryptMetadataOnly(boolean decryptMetadataOnly) {
mDecryptMetadataOnly = decryptMetadataOnly;
return this;
}
byte[] getDetachedSignature() {
return mDetachedSignature;
}
public PgpDecryptVerifyInputParcel setDetachedSignature(byte[] detachedSignature) {
mDetachedSignature = detachedSignature;
return this;
}
String getRequiredSignerFingerprint() {
return mRequiredSignerFingerprint;
}
public PgpDecryptVerifyInputParcel setRequiredSignerFingerprint(String requiredSignerFingerprint) {
mRequiredSignerFingerprint = requiredSignerFingerprint;
return this;
}
boolean isSignedLiteralData() {
return mSignedLiteralData;
}
public PgpDecryptVerifyInputParcel setSignedLiteralData(boolean signedLiteralData) {
mSignedLiteralData = signedLiteralData;
return this;
}
public static final Creator<PgpDecryptVerifyInputParcel> CREATOR = new Creator<PgpDecryptVerifyInputParcel>() {
public PgpDecryptVerifyInputParcel createFromParcel(final Parcel source) {
return new PgpDecryptVerifyInputParcel(source);
}
public PgpDecryptVerifyInputParcel[] newArray(final int size) {
return new PgpDecryptVerifyInputParcel[size];
}
};
}

View file

@ -1514,8 +1514,8 @@ public class ProviderHelper {
return keyIds; return keyIds;
} }
public Set<Long> getAllowedKeyIdsForApp(Uri uri) { public HashSet<Long> getAllowedKeyIdsForApp(Uri uri) {
Set<Long> keyIds = new HashSet<>(); HashSet<Long> keyIds = new HashSet<>();
Cursor cursor = mContentResolver.query(uri, null, null, null, null); Cursor cursor = mContentResolver.query(uri, null, null, null, null);
try { try {

View file

@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEnt
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpConstants; import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
@ -63,7 +64,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set; import java.util.HashSet;
public class OpenPgpService extends RemoteService { public class OpenPgpService extends RemoteService {
@ -488,23 +489,23 @@ public class OpenPgpService extends RemoteService {
} }
} }
private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input, private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor inputDescriptor,
ParcelFileDescriptor output, boolean decryptMetadataOnly) { ParcelFileDescriptor output, boolean decryptMetadataOnly) {
InputStream is = null; InputStream inputStream = null;
OutputStream os = null; OutputStream outputStream = null;
try { try {
// Get Input- and OutputStream from ParcelFileDescriptor // Get Input- and OutputStream from ParcelFileDescriptor
is = new ParcelFileDescriptor.AutoCloseInputStream(input); inputStream = new ParcelFileDescriptor.AutoCloseInputStream(inputDescriptor);
// output is optional, e.g., for verifying detached signatures // output is optional, e.g., for verifying detached signatures
if (decryptMetadataOnly || output == null) { if (decryptMetadataOnly || output == null) {
os = null; outputStream = null;
} else { } else {
os = new ParcelFileDescriptor.AutoCloseOutputStream(output); outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(output);
} }
String currentPkg = getCurrentCallingPackage(); String currentPkg = getCurrentCallingPackage();
Set<Long> allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp( HashSet<Long> allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp(
KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) { if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) {
@ -512,33 +513,31 @@ public class OpenPgpService extends RemoteService {
ApiAccounts.buildBaseUri(currentPkg))); ApiAccounts.buildBaseUri(currentPkg)));
} }
long inputLength = is.available(); CryptoInputParcel cryptoInput = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
InputData inputData = new InputData(is, inputLength); if (cryptoInput == null) {
cryptoInput = new CryptoInputParcel();
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
this, new ProviderHelper(getContext()), null, inputData, os
);
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (inputParcel == null) {
inputParcel = new CryptoInputParcel();
} }
// override passphrase in input parcel if given by API call // override passphrase in input parcel if given by API call
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(), cryptoInput = new CryptoInputParcel(cryptoInput.getSignatureTime(),
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE))); new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
} }
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE); byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
PgpDecryptVerify op = new PgpDecryptVerify(this, mProviderHelper, null);
long inputLength = inputStream.available();
// allow only private keys associated with accounts of this app // allow only private keys associated with accounts of this app
// no support for symmetric encryption // no support for symmetric encryption
builder.setAllowSymmetricDecryption(false) PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel()
.setAllowedKeyIds(allowedKeyIds) .setAllowSymmetricDecryption(false)
.setDecryptMetadataOnly(decryptMetadataOnly) .setAllowedKeyIds(allowedKeyIds)
.setDetachedSignature(detachedSignature); .setDecryptMetadataOnly(decryptMetadataOnly)
.setDetachedSignature(detachedSignature);
DecryptVerifyResult pgpResult = builder.build().execute(inputParcel); DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputStream, outputStream);
if (pgpResult.isPending()) { if (pgpResult.isPending()) {
// prepare and return PendingIntent to be executed by client // prepare and return PendingIntent to be executed by client
@ -624,16 +623,16 @@ public class OpenPgpService extends RemoteService {
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
return result; return result;
} finally { } finally {
if (is != null) { if (inputStream != null) {
try { try {
is.close(); inputStream.close();
} catch (IOException e) { } catch (IOException e) {
Log.e(Constants.TAG, "IOException when closing InputStream", e); Log.e(Constants.TAG, "IOException when closing InputStream", e);
} }
} }
if (os != null) { if (outputStream != null) {
try { try {
os.close(); outputStream.close();
} catch (IOException e) { } catch (IOException e) {
Log.e(Constants.TAG, "IOException when closing OutputStream", e); Log.e(Constants.TAG, "IOException when closing OutputStream", e);
} }

View file

@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@ -61,17 +62,11 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -122,34 +117,13 @@ public class KeychainIntentService extends IntentService implements Progressable
/* keys for data bundle */ /* keys for data bundle */
// encrypt, decrypt, import export
public static final String TARGET = "target";
public static final String SOURCE = "source";
// possible targets:
public static enum IOType {
UNKNOWN,
BYTES,
URI;
private static final IOType[] values = values();
public static IOType fromInt(int n) {
if (n < 0 || n >= values.length) {
return UNKNOWN;
} else {
return values[n];
}
}
}
// encrypt // encrypt
public static final String ENCRYPT_DECRYPT_INPUT_URI = "input_uri"; public static final String ENCRYPT_DECRYPT_INPUT_URI = "input_uri";
public static final String ENCRYPT_DECRYPT_OUTPUT_URI = "output_uri"; public static final String ENCRYPT_DECRYPT_OUTPUT_URI = "output_uri";
public static final String SIGN_ENCRYPT_PARCEL = "sign_encrypt_parcel"; public static final String SIGN_ENCRYPT_PARCEL = "sign_encrypt_parcel";
// decrypt/verify // decrypt/verify
public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; public static final String DECRYPT_VERIFY_PARCEL = "decrypt_verify_parcel";
// keybase proof // keybase proof
public static final String KEYBASE_REQUIRED_FINGERPRINT = "keybase_required_fingerprint"; public static final String KEYBASE_REQUIRED_FINGERPRINT = "keybase_required_fingerprint";
@ -189,14 +163,6 @@ public class KeychainIntentService extends IntentService implements Progressable
// consolidate // consolidate
public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery"; public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery";
/*
* possible data keys as result send over messenger
*/
// decrypt/verify
public static final String RESULT_DECRYPTED_BYTES = "decrypted_data";
Messenger mMessenger; Messenger mMessenger;
// this attribute can possibly merged with the one above? not sure... // this attribute can possibly merged with the one above? not sure...
@ -280,26 +246,16 @@ public class KeychainIntentService extends IntentService implements Progressable
} }
case ACTION_DECRYPT_METADATA: { case ACTION_DECRYPT_METADATA: {
try { /* Input */
/* Input */ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT); PgpDecryptVerifyInputParcel input = data.getParcelable(DECRYPT_VERIFY_PARCEL);
InputData inputData = createDecryptInputData(data); // verifyText and decrypt returning additional resultData values for the
// verification of signatures
PgpDecryptVerify op = new PgpDecryptVerify(this, new ProviderHelper(this), this);
DecryptVerifyResult decryptVerifyResult = op.execute(input, cryptoInput);
// verifyText and decrypt returning additional resultData values for the sendMessageToHandler(MessageStatus.OKAY, decryptVerifyResult);
// verification of signatures
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
this, new ProviderHelper(this), this, inputData, null
);
builder.setAllowSymmetricDecryption(true)
.setDecryptMetadataOnly(true);
DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput);
sendMessageToHandler(MessageStatus.OKAY, decryptVerifyResult);
} catch (Exception e) {
sendErrorToHandler(e);
}
break; break;
} }
@ -356,22 +312,13 @@ public class KeychainIntentService extends IntentService implements Progressable
} }
} }
// kind of awkward, but this whole class wants to pull bytes out of data PgpDecryptVerify op = new PgpDecryptVerify(this, new ProviderHelper(this), this);
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, messageBytes);
InputData inputData = createDecryptInputData(data); PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
OutputStream outStream = createCryptOutputStream(data); .setSignedLiteralData(true)
.setRequiredSignerFingerprint(requiredFingerprint);
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
this, new ProviderHelper(this), this,
inputData, outStream
);
builder.setSignedLiteralData(true).setRequiredSignerFingerprint(requiredFingerprint);
DecryptVerifyResult decryptVerifyResult = builder.build().execute(
new CryptoInputParcel());
outStream.close();
if (!decryptVerifyResult.success()) { if (!decryptVerifyResult.success()) {
OperationLog log = decryptVerifyResult.getLog(); OperationLog log = decryptVerifyResult.getLog();
@ -383,7 +330,7 @@ public class KeychainIntentService extends IntentService implements Progressable
return; return;
} }
if (!prover.validate(outStream.toString())) { if (!prover.validate(new String(decryptVerifyResult.getOutputBytes()))) {
sendProofError(getString(R.string.keybase_message_payload_mismatch)); sendProofError(getString(R.string.keybase_message_payload_mismatch));
return; return;
} }
@ -404,40 +351,16 @@ public class KeychainIntentService extends IntentService implements Progressable
} }
case ACTION_DECRYPT_VERIFY: { case ACTION_DECRYPT_VERIFY: {
try { /* Input */
/* Input */ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT); PgpDecryptVerifyInputParcel input = data.getParcelable(DECRYPT_VERIFY_PARCEL);
InputData inputData = createDecryptInputData(data); /* Operation */
OutputStream outStream = createCryptOutputStream(data); PgpDecryptVerify op = new PgpDecryptVerify(this, new ProviderHelper(this), this);
DecryptVerifyResult decryptVerifyResult = op.execute(input, cryptoInput);
/* Operation */ /* Output */
Bundle resultData = new Bundle(); sendMessageToHandler(MessageStatus.OKAY, decryptVerifyResult);
// verifyText and decrypt returning additional resultData values for the
// verification of signatures
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
this, new ProviderHelper(this), this,
inputData, outStream
);
builder.setAllowSymmetricDecryption(true);
DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput);
outStream.close();
resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult);
/* Output */
finalizeDecryptOutputStream(data, resultData, outStream);
Log.logDebugBundle(resultData, "resultData");
sendMessageToHandler(MessageStatus.OKAY, resultData);
} catch (IOException | PgpGeneralException e) {
// TODO get rid of this!
sendErrorToHandler(e);
}
break; break;
} }
@ -676,65 +599,6 @@ public class KeychainIntentService extends IntentService implements Progressable
sendMessageToHandler(MessageStatus.PREVENT_CANCEL); sendMessageToHandler(MessageStatus.PREVENT_CANCEL);
} }
private InputData createDecryptInputData(Bundle data) throws IOException, PgpGeneralException {
return createCryptInputData(data, DECRYPT_CIPHERTEXT_BYTES);
}
private InputData createCryptInputData(Bundle data, String bytesName) throws PgpGeneralException, IOException {
int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET);
IOType type = IOType.fromInt(source);
switch (type) {
case BYTES: /* encrypting bytes directly */
byte[] bytes = data.getByteArray(bytesName);
return new InputData(new ByteArrayInputStream(bytes), bytes.length);
case URI: /* encrypting content uri */
Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_INPUT_URI);
// InputStream
return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0));
default:
throw new PgpGeneralException("No target chosen!");
}
}
private OutputStream createCryptOutputStream(Bundle data) throws PgpGeneralException, FileNotFoundException {
int target = data.getInt(TARGET);
IOType type = IOType.fromInt(target);
switch (type) {
case BYTES:
return new ByteArrayOutputStream();
case URI:
Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_OUTPUT_URI);
return getContentResolver().openOutputStream(providerUri);
default:
throw new PgpGeneralException("No target chosen!");
}
}
private void finalizeDecryptOutputStream(Bundle data, Bundle resultData, OutputStream outStream) {
finalizeCryptOutputStream(data, resultData, outStream, RESULT_DECRYPTED_BYTES);
}
private void finalizeCryptOutputStream(Bundle data, Bundle resultData, OutputStream outStream, String bytesName) {
int target = data.getInt(TARGET);
IOType type = IOType.fromInt(target);
switch (type) {
case BYTES:
byte output[] = ((ByteArrayOutputStream) outStream).toByteArray();
resultData.putByteArray(bytesName, output);
break;
case URI:
// nothing, output was written, just send okay and verification bundle
break;
}
}
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_CANCEL.equals(intent.getAction())) { if (ACTION_CANCEL.equals(intent.getAction())) {

View file

@ -36,8 +36,8 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentService.IOType;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
@ -202,16 +202,14 @@ public class DecryptFilesFragment extends DecryptFragment {
intent.setAction(mCurrentCryptoOperation); intent.setAction(mCurrentCryptoOperation);
// data // data
data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
data.putInt(KeychainIntentService.SOURCE, IOType.URI.ordinal()); PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mInputUri, mOutputUri)
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_INPUT_URI, mInputUri); .setAllowSymmetricDecryption(true)
.setDecryptMetadataOnly(true);
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input);
data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);

View file

@ -34,8 +34,8 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentService.IOType;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
@ -168,10 +168,8 @@ public class DecryptTextFragment extends DecryptFragment {
intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY); intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY);
// data PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCiphertext.getBytes());
data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input);
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -199,8 +197,7 @@ public class DecryptTextFragment extends DecryptFragment {
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
if (pgpResult.success()) { if (pgpResult.success()) {
byte[] decryptedMessage = returnData byte[] decryptedMessage = pgpResult.getOutputBytes();
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
String displayMessage; String displayMessage;
if (pgpResult.getCharset() != null) { if (pgpResult.getCharset() != null) {
try { try {

View file

@ -120,6 +120,9 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment {
// preselect keys given, from state or arguments // preselect keys given, from state or arguments
if (savedInstanceState == null) { if (savedInstanceState == null) {
Long signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID); Long signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID);
if (signatureKeyId == Constants.key.none) {
signatureKeyId = null;
}
long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS); long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS);
preselectKeys(signatureKeyId, encryptionKeyIds); preselectKeys(signatureKeyId, encryptionKeyIds);
} }

View file

@ -163,9 +163,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong(EXTRA_SUBKEY_ID, keyId); args.putLong(EXTRA_SUBKEY_ID, keyId);
args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent); args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent);
frag.setArguments(args); frag.setArguments(args);
frag.show(context.getSupportFragmentManager(), "passphraseDialog"); frag.show(context.getSupportFragmentManager(), "passphraseDialog");
} }
}); });