Merge pull request #1771 from runnerway/refactoring-operation

PgpSignEncryptOperation refactoring
This commit is contained in:
Dominik Schürmann
2016-05-11 09:00:22 +03:00
13 changed files with 565 additions and 392 deletions

View File

@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
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.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
@@ -151,10 +152,11 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
PgpSignEncryptOperation pseOp = new PgpSignEncryptOperation(mContext, mProviderHelper, mProgressable, mCancelled); PgpSignEncryptOperation pseOp = new PgpSignEncryptOperation(mContext, mProviderHelper, mProgressable, mCancelled);
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(); PgpSignEncryptData data = new PgpSignEncryptData();
inputParcel.setSymmetricPassphrase(cryptoInput.getPassphrase()); data.setSymmetricPassphrase(cryptoInput.getPassphrase());
inputParcel.setEnableAsciiArmorOutput(true); data.setEnableAsciiArmorOutput(true);
inputParcel.setAddBackupHeader(true); data.setAddBackupHeader(true);
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(data);
InputStream inStream = mContext.getContentResolver().openInputStream(plainUri); InputStream inStream = mContext.getContentResolver().openInputStream(plainUri);

View File

@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
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.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
@@ -83,9 +84,10 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
SignEncryptOperation op = SignEncryptOperation op =
new SignEncryptOperation(mContext, mProviderHelper, new SignEncryptOperation(mContext, mProviderHelper,
new ProgressScaler(mProgressable, i*(50/numRepeats), (i+1)*(50/numRepeats), 100), mCancelled); new ProgressScaler(mProgressable, i*(50/numRepeats), (i+1)*(50/numRepeats), 100), mCancelled);
SignEncryptParcel input = new SignEncryptParcel(); PgpSignEncryptData data = new PgpSignEncryptData();
input.setSymmetricPassphrase(passphrase); data.setSymmetricPassphrase(passphrase);
input.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.AES_128); data.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
SignEncryptParcel input = new SignEncryptParcel(data);
input.setBytes(buf); input.setBytes(buf);
encryptResult = op.execute(input, new CryptoInputParcel()); encryptResult = op.execute(input, new CryptoInputParcel());
log.add(encryptResult, 1); log.add(encryptResult, 1);

View File

@@ -18,15 +18,6 @@
package org.sufficientlysecure.keychain.operations; package org.sufficientlysecure.keychain.operations;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@@ -36,6 +27,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
@@ -45,16 +38,18 @@ 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.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
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.ProgressScaler; import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* This is a high-level operation, which encapsulates one or more sign/encrypt * This is a high-level operation, which encapsulates one or more sign/encrypt
* operations, using URIs or byte arrays as input and output. * operations, using URIs or byte arrays as input and output.
* * <p/>
* This operation is fail-fast: If any sign/encrypt sub-operation fails or returns * This operation is fail-fast: If any sign/encrypt sub-operation fails or returns
* a pending result, it will terminate. * a pending result, it will terminate.
*/ */
@@ -75,20 +70,20 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
ArrayDeque<Uri> inputUris = new ArrayDeque<>(input.getInputUris()); ArrayDeque<Uri> inputUris = new ArrayDeque<>(input.getInputUris());
ArrayDeque<Uri> outputUris = new ArrayDeque<>(input.getOutputUris()); ArrayDeque<Uri> outputUris = new ArrayDeque<>(input.getOutputUris());
byte[] inputBytes = input.getBytes(); byte[] inputBytes = input.getBytes();
byte[] outputBytes = null;
int total = inputBytes != null ? 1 : inputUris.size(), count = 0; int total = inputBytes != null ? 1 : inputUris.size(), count = 0;
ArrayList<PgpSignEncryptResult> results = new ArrayList<>(); ArrayList<PgpSignEncryptResult> results = new ArrayList<>();
SecurityTokenSignOperationsBuilder pendingInputBuilder = null; SecurityTokenSignOperationsBuilder pendingInputBuilder = null;
PgpSignEncryptData data = input.getData();
// if signing subkey has not explicitly been set, get first usable subkey capable of signing // if signing subkey has not explicitly been set, get first usable subkey capable of signing
if (input.getSignatureMasterKeyId() != Constants.key.none if (data.getSignatureMasterKeyId() != Constants.key.none
&& input.getSignatureSubKeyId() == null) { && data.getSignatureSubKeyId() == null) {
try { try {
long signKeyId = mProviderHelper.getCachedPublicKeyRing( long signKeyId = mProviderHelper.getCachedPublicKeyRing(
input.getSignatureMasterKeyId()).getSecretSignId(); data.getSignatureMasterKeyId()).getSecretSignId();
input.setSignatureSubKeyId(signKeyId); data.setSignatureSubKeyId(signKeyId);
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "Key not found", e); Log.e(Constants.TAG, "Key not found", e);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results); return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
@@ -96,61 +91,22 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
} }
do { do {
if (checkCancelled()) { if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED, 0); log.add(LogType.MSG_OPERATION_CANCELLED, 0);
return new SignEncryptResult(SignEncryptResult.RESULT_CANCELLED, log, results); return new SignEncryptResult(SignEncryptResult.RESULT_CANCELLED, log, results);
} }
InputData inputData;
{
if (inputBytes != null) {
log.add(LogType.MSG_SE_INPUT_BYTES, 1);
InputStream is = new ByteArrayInputStream(inputBytes);
inputData = new InputData(is, inputBytes.length);
inputBytes = null;
} else {
if (inputUris.isEmpty()) {
log.add(LogType.MSG_SE_ERROR_NO_INPUT, 1);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
log.add(LogType.MSG_SE_INPUT_URI, 1);
Uri uri = inputUris.removeFirst();
try {
InputStream is = FileHelper.openInputStreamSafe(mContext.getContentResolver(), uri);
long fileSize = FileHelper.getFileSize(mContext, uri, 0);
String filename = FileHelper.getFilename(mContext, uri);
inputData = new InputData(is, fileSize, filename);
} catch (FileNotFoundException e) {
log.add(LogType.MSG_SE_ERROR_INPUT_URI_NOT_FOUND, 1);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
}
}
OutputStream outStream;
{
if (!outputUris.isEmpty()) {
try {
Uri outputUri = outputUris.removeFirst();
outStream = mContext.getContentResolver().openOutputStream(outputUri);
} catch (FileNotFoundException e) {
log.add(LogType.MSG_SE_ERROR_OUTPUT_URI_NOT_FOUND, 1);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
} else {
if (outputBytes != null) {
log.add(LogType.MSG_SE_ERROR_TOO_MANY_INPUTS, 1);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
outStream = new ByteArrayOutputStream();
}
}
PgpSignEncryptOperation op = new PgpSignEncryptOperation(mContext, mProviderHelper, PgpSignEncryptOperation op = new PgpSignEncryptOperation(mContext, mProviderHelper,
new ProgressScaler(mProgressable, 100 * count / total, 100 * ++count / total, 100), mCancelled); new ProgressScaler(mProgressable, 100 * count / total, 100 * ++count / total, 100), mCancelled);
PgpSignEncryptResult result = op.execute(input, cryptoInput, inputData, outStream); PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(input.getData());
if (inputBytes != null) {
inputParcel.setInputBytes(inputBytes);
} else {
inputParcel.setInputUri(inputUris.removeFirst());
}
inputParcel.setOutputUri(outputUris.pollFirst());
PgpSignEncryptResult result = op.execute(inputParcel, cryptoInput);
results.add(result); results.add(result);
log.add(result, 2); log.add(result, 2);
@@ -162,17 +118,12 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
} }
if (pendingInputBuilder == null) { if (pendingInputBuilder == null) {
pendingInputBuilder = new SecurityTokenSignOperationsBuilder(requiredInput.mSignatureTime, pendingInputBuilder = new SecurityTokenSignOperationsBuilder(requiredInput.mSignatureTime,
input.getSignatureMasterKeyId(), input.getSignatureSubKeyId()); data.getSignatureMasterKeyId(), data.getSignatureSubKeyId());
} }
pendingInputBuilder.addAll(requiredInput); pendingInputBuilder.addAll(requiredInput);
} else if (!result.success()) { } else if (!result.success()) {
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results); return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
} }
if (outStream instanceof ByteArrayOutputStream) {
outputBytes = ((ByteArrayOutputStream) outStream).toByteArray();
}
} while (!inputUris.isEmpty()); } while (!inputUris.isEmpty());
if (pendingInputBuilder != null && !pendingInputBuilder.isEmpty()) { if (pendingInputBuilder != null && !pendingInputBuilder.isEmpty()) {
@@ -184,8 +135,8 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
} }
log.add(LogType.MSG_SE_SUCCESS, 1); log.add(LogType.MSG_SE_SUCCESS, 1);
return new SignEncryptResult(SignEncryptResult.RESULT_OK, log, results, outputBytes); return new SignEncryptResult(SignEncryptResult.RESULT_OK, log, results,
results.get(results.size() - 1).getOutputBytes());
} }
} }

View File

@@ -710,15 +710,15 @@ public abstract class OperationResult implements Parcelable {
// signencrypt // signencrypt
MSG_SE (LogLevel.START, R.string.msg_se), MSG_SE (LogLevel.START, R.string.msg_se),
MSG_SE_INPUT_BYTES (LogLevel.INFO, R.string.msg_se_input_bytes),
MSG_SE_INPUT_URI (LogLevel.INFO, R.string.msg_se_input_uri),
MSG_SE_ERROR_NO_INPUT (LogLevel.DEBUG, R.string.msg_se_error_no_input), MSG_SE_ERROR_NO_INPUT (LogLevel.DEBUG, R.string.msg_se_error_no_input),
MSG_SE_ERROR_INPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_input_uri_not_found),
MSG_SE_ERROR_OUTPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_output_uri_not_found),
MSG_SE_ERROR_TOO_MANY_INPUTS (LogLevel.ERROR, R.string.msg_se_error_too_many_inputs), MSG_SE_ERROR_TOO_MANY_INPUTS (LogLevel.ERROR, R.string.msg_se_error_too_many_inputs),
MSG_SE_SUCCESS (LogLevel.OK, R.string.msg_se_success), MSG_SE_SUCCESS (LogLevel.OK, R.string.msg_se_success),
// pgpsignencrypt // pgpsignencrypt
MSG_PSE_INPUT_BYTES (LogLevel.INFO, R.string.msg_se_input_bytes),
MSG_PSE_INPUT_URI (LogLevel.INFO, R.string.msg_se_input_uri),
MSG_PSE_ERROR_INPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_input_uri_not_found),
MSG_PSE_ERROR_OUTPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_output_uri_not_found),
MSG_PSE_ASYMMETRIC (LogLevel.INFO, R.string.msg_pse_asymmetric), MSG_PSE_ASYMMETRIC (LogLevel.INFO, R.string.msg_pse_asymmetric),
MSG_PSE_COMPRESSING (LogLevel.DEBUG, R.string.msg_pse_compressing), MSG_PSE_COMPRESSING (LogLevel.DEBUG, R.string.msg_pse_compressing),
MSG_PSE_ENCRYPTING (LogLevel.DEBUG, R.string.msg_pse_encrypting), MSG_PSE_ENCRYPTING (LogLevel.DEBUG, R.string.msg_pse_encrypting),

View File

@@ -25,6 +25,8 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
public class PgpSignEncryptResult extends InputPendingResult { public class PgpSignEncryptResult extends InputPendingResult {
byte[] mOutputBytes;
byte[] mDetachedSignature; byte[] mDetachedSignature;
public long mOperationTime; public long mOperationTime;
// this is the micalg parameter used in PGP/MIME, see RFC3156: // this is the micalg parameter used in PGP/MIME, see RFC3156:
@@ -53,6 +55,14 @@ public class PgpSignEncryptResult extends InputPendingResult {
mDetachedSignature = source.readInt() != 0 ? source.createByteArray() : null; mDetachedSignature = source.readInt() != 0 ? source.createByteArray() : null;
} }
public void setOutputBytes(byte[] outputBytes) {
mOutputBytes = outputBytes;
}
public byte[] getOutputBytes() {
return mOutputBytes;
}
public int describeContents() { public int describeContents() {
return 0; return 0;
} }

View File

@@ -0,0 +1,259 @@
/*
* 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 android.os.Parcel;
import android.os.Parcelable;
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Passphrase;
public class PgpSignEncryptData implements Parcelable {
protected String mVersionHeader = null;
protected boolean mEnableAsciiArmorOutput = false;
protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null;
protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
protected long mAdditionalEncryptId = Constants.key.none;
protected String mCharset;
protected boolean mCleartextSignature;
protected boolean mDetachedSignature = false;
protected boolean mHiddenRecipients = false;
protected boolean mIntegrityProtected = true;
protected boolean mAddBackupHeader = false;
public PgpSignEncryptData(){
}
PgpSignEncryptData(Parcel source) {
ClassLoader loader = getClass().getClassLoader();
mVersionHeader = source.readString();
mEnableAsciiArmorOutput = source.readInt() == 1;
mCompressionAlgorithm = source.readInt();
mEncryptionMasterKeyIds = source.createLongArray();
mSymmetricPassphrase = source.readParcelable(loader);
mSymmetricEncryptionAlgorithm = source.readInt();
mSignatureMasterKeyId = source.readLong();
mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
mSignatureHashAlgorithm = source.readInt();
mAdditionalEncryptId = source.readLong();
mCharset = source.readString();
mCleartextSignature = source.readInt() == 1;
mDetachedSignature = source.readInt() == 1;
mHiddenRecipients = source.readInt() == 1;
mIntegrityProtected = source.readInt() == 1;
mAddBackupHeader = source.readInt() == 1;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mVersionHeader);
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
dest.writeInt(mCompressionAlgorithm);
dest.writeLongArray(mEncryptionMasterKeyIds);
dest.writeParcelable(mSymmetricPassphrase, 0);
dest.writeInt(mSymmetricEncryptionAlgorithm);
dest.writeLong(mSignatureMasterKeyId);
if (mSignatureSubKeyId != null) {
dest.writeInt(1);
dest.writeLong(mSignatureSubKeyId);
} else {
dest.writeInt(0);
}
dest.writeInt(mSignatureHashAlgorithm);
dest.writeLong(mAdditionalEncryptId);
dest.writeString(mCharset);
dest.writeInt(mCleartextSignature ? 1 : 0);
dest.writeInt(mDetachedSignature ? 1 : 0);
dest.writeInt(mHiddenRecipients ? 1 : 0);
dest.writeInt(mIntegrityProtected ? 1 : 0);
dest.writeInt(mAddBackupHeader ? 1 : 0);
}
public String getCharset() {
return mCharset;
}
public void setCharset(String mCharset) {
this.mCharset = mCharset;
}
public long getAdditionalEncryptId() {
return mAdditionalEncryptId;
}
public PgpSignEncryptData setAdditionalEncryptId(long additionalEncryptId) {
mAdditionalEncryptId = additionalEncryptId;
return this;
}
public int getSignatureHashAlgorithm() {
return mSignatureHashAlgorithm;
}
public PgpSignEncryptData setSignatureHashAlgorithm(int signatureHashAlgorithm) {
mSignatureHashAlgorithm = signatureHashAlgorithm;
return this;
}
public Long getSignatureSubKeyId() {
return mSignatureSubKeyId;
}
public PgpSignEncryptData setSignatureSubKeyId(long signatureSubKeyId) {
mSignatureSubKeyId = signatureSubKeyId;
return this;
}
public long getSignatureMasterKeyId() {
return mSignatureMasterKeyId;
}
public PgpSignEncryptData setSignatureMasterKeyId(long signatureMasterKeyId) {
mSignatureMasterKeyId = signatureMasterKeyId;
return this;
}
public int getSymmetricEncryptionAlgorithm() {
return mSymmetricEncryptionAlgorithm;
}
public PgpSignEncryptData setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
return this;
}
public Passphrase getSymmetricPassphrase() {
return mSymmetricPassphrase;
}
public PgpSignEncryptData setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
public long[] getEncryptionMasterKeyIds() {
return mEncryptionMasterKeyIds;
}
public PgpSignEncryptData setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
return this;
}
public int getCompressionAlgorithm() {
return mCompressionAlgorithm;
}
public PgpSignEncryptData setCompressionAlgorithm(int compressionAlgorithm) {
mCompressionAlgorithm = compressionAlgorithm;
return this;
}
public boolean isEnableAsciiArmorOutput() {
return mEnableAsciiArmorOutput;
}
public String getVersionHeader() {
return mVersionHeader;
}
public PgpSignEncryptData setVersionHeader(String versionHeader) {
mVersionHeader = versionHeader;
return this;
}
public PgpSignEncryptData setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this;
}
public PgpSignEncryptData setCleartextSignature(boolean cleartextSignature) {
this.mCleartextSignature = cleartextSignature;
return this;
}
public boolean isCleartextSignature() {
return mCleartextSignature;
}
public PgpSignEncryptData setDetachedSignature(boolean detachedSignature) {
this.mDetachedSignature = detachedSignature;
return this;
}
public boolean isDetachedSignature() {
return mDetachedSignature;
}
public PgpSignEncryptData setHiddenRecipients(boolean hiddenRecipients) {
this.mHiddenRecipients = hiddenRecipients;
return this;
}
public boolean isIntegrityProtected() {
return mIntegrityProtected;
}
/**
* Only use for testing! Never disable integrity protection!
*/
public PgpSignEncryptData setIntegrityProtected(boolean integrityProtected) {
this.mIntegrityProtected = integrityProtected;
return this;
}
public PgpSignEncryptData setAddBackupHeader(boolean addBackupHeader) {
this.mAddBackupHeader = addBackupHeader;
return this;
}
public boolean isAddBackupHeader() {
return mAddBackupHeader;
}
public boolean isHiddenRecipients() {
return mHiddenRecipients;
}
public static final Creator<PgpSignEncryptData> CREATOR = new Creator<PgpSignEncryptData>() {
public PgpSignEncryptData createFromParcel(final Parcel source) {
return new PgpSignEncryptData(source);
}
public PgpSignEncryptData[] newArray(final int size) {
return new PgpSignEncryptData[size];
}
};
}

View File

@@ -18,58 +18,29 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import org.bouncycastle.bcpg.CompressionAlgorithmTags; import android.net.Uri;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Passphrase;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
public class PgpSignEncryptInputParcel implements Parcelable { public class PgpSignEncryptInputParcel implements Parcelable {
protected String mVersionHeader = null; private PgpSignEncryptData data;
protected boolean mEnableAsciiArmorOutput = false;
protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null;
protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
protected long mAdditionalEncryptId = Constants.key.none;
protected String mCharset;
protected boolean mCleartextSignature;
protected boolean mDetachedSignature = false;
protected boolean mHiddenRecipients = false;
protected boolean mIntegrityProtected = true;
protected boolean mAddBackupHeader = false;
public PgpSignEncryptInputParcel() { private Uri mInputUri;
private Uri mOutputUri;
private byte[] mInputBytes;
public PgpSignEncryptInputParcel(PgpSignEncryptData data) {
this.data = data;
} }
PgpSignEncryptInputParcel(Parcel source) { PgpSignEncryptInputParcel(Parcel source) {
mInputUri = source.readParcelable(getClass().getClassLoader());
mOutputUri = source.readParcelable(getClass().getClassLoader());
mInputBytes = source.createByteArray();
ClassLoader loader = getClass().getClassLoader(); data = source.readParcelable(getClass().getClassLoader());
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mVersionHeader = source.readString();
mEnableAsciiArmorOutput = source.readInt() == 1;
mCompressionAlgorithm = source.readInt();
mEncryptionMasterKeyIds = source.createLongArray();
mSymmetricPassphrase = source.readParcelable(loader);
mSymmetricEncryptionAlgorithm = source.readInt();
mSignatureMasterKeyId = source.readLong();
mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
mSignatureHashAlgorithm = source.readInt();
mAdditionalEncryptId = source.readLong();
mCharset = source.readString();
mCleartextSignature = source.readInt() == 1;
mDetachedSignature = source.readInt() == 1;
mHiddenRecipients = source.readInt() == 1;
mIntegrityProtected = source.readInt() == 1;
mAddBackupHeader = source.readInt() == 1;
} }
@Override @Override
@@ -79,173 +50,45 @@ public class PgpSignEncryptInputParcel implements Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mVersionHeader); dest.writeParcelable(mInputUri, 0);
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0); dest.writeParcelable(mOutputUri, 0);
dest.writeInt(mCompressionAlgorithm); dest.writeByteArray(mInputBytes);
dest.writeLongArray(mEncryptionMasterKeyIds);
dest.writeParcelable(mSymmetricPassphrase, 0); data.writeToParcel(dest, 0);
dest.writeInt(mSymmetricEncryptionAlgorithm);
dest.writeLong(mSignatureMasterKeyId);
if (mSignatureSubKeyId != null) {
dest.writeInt(1);
dest.writeLong(mSignatureSubKeyId);
} else {
dest.writeInt(0);
}
dest.writeInt(mSignatureHashAlgorithm);
dest.writeLong(mAdditionalEncryptId);
dest.writeString(mCharset);
dest.writeInt(mCleartextSignature ? 1 : 0);
dest.writeInt(mDetachedSignature ? 1 : 0);
dest.writeInt(mHiddenRecipients ? 1 : 0);
dest.writeInt(mIntegrityProtected ? 1 : 0);
dest.writeInt(mAddBackupHeader ? 1 : 0);
} }
public String getCharset() { public void setInputBytes(byte[] inputBytes) {
return mCharset; this.mInputBytes = inputBytes;
} }
public void setCharset(String mCharset) { byte[] getInputBytes() {
this.mCharset = mCharset; return mInputBytes;
} }
public long getAdditionalEncryptId() { public PgpSignEncryptInputParcel setInputUri(Uri uri) {
return mAdditionalEncryptId; mInputUri = uri;
}
public PgpSignEncryptInputParcel setAdditionalEncryptId(long additionalEncryptId) {
mAdditionalEncryptId = additionalEncryptId;
return this; return this;
} }
public int getSignatureHashAlgorithm() { Uri getInputUri() {
return mSignatureHashAlgorithm; return mInputUri;
} }
public PgpSignEncryptInputParcel setSignatureHashAlgorithm(int signatureHashAlgorithm) { public PgpSignEncryptInputParcel setOutputUri(Uri uri) {
mSignatureHashAlgorithm = signatureHashAlgorithm; mOutputUri = uri;
return this; return this;
} }
public Long getSignatureSubKeyId() { Uri getOutputUri() {
return mSignatureSubKeyId; return mOutputUri;
} }
public PgpSignEncryptInputParcel setSignatureSubKeyId(long signatureSubKeyId) { public void setData(PgpSignEncryptData data) {
mSignatureSubKeyId = signatureSubKeyId; this.data = data;
return this;
} }
public long getSignatureMasterKeyId() { public PgpSignEncryptData getData() {
return mSignatureMasterKeyId; return data;
}
public PgpSignEncryptInputParcel setSignatureMasterKeyId(long signatureMasterKeyId) {
mSignatureMasterKeyId = signatureMasterKeyId;
return this;
}
public int getSymmetricEncryptionAlgorithm() {
return mSymmetricEncryptionAlgorithm;
}
public PgpSignEncryptInputParcel setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
return this;
}
public Passphrase getSymmetricPassphrase() {
return mSymmetricPassphrase;
}
public PgpSignEncryptInputParcel setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
public long[] getEncryptionMasterKeyIds() {
return mEncryptionMasterKeyIds;
}
public PgpSignEncryptInputParcel setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
return this;
}
public int getCompressionAlgorithm() {
return mCompressionAlgorithm;
}
public PgpSignEncryptInputParcel setCompressionAlgorithm(int compressionAlgorithm) {
mCompressionAlgorithm = compressionAlgorithm;
return this;
}
public boolean isEnableAsciiArmorOutput() {
return mEnableAsciiArmorOutput;
}
public String getVersionHeader() {
return mVersionHeader;
}
public PgpSignEncryptInputParcel setVersionHeader(String versionHeader) {
mVersionHeader = versionHeader;
return this;
}
public PgpSignEncryptInputParcel setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this;
}
public PgpSignEncryptInputParcel setCleartextSignature(boolean cleartextSignature) {
this.mCleartextSignature = cleartextSignature;
return this;
}
public boolean isCleartextSignature() {
return mCleartextSignature;
}
public PgpSignEncryptInputParcel setDetachedSignature(boolean detachedSignature) {
this.mDetachedSignature = detachedSignature;
return this;
}
public boolean isDetachedSignature() {
return mDetachedSignature;
}
public PgpSignEncryptInputParcel setHiddenRecipients(boolean hiddenRecipients) {
this.mHiddenRecipients = hiddenRecipients;
return this;
}
public boolean isIntegrityProtected() {
return mIntegrityProtected;
}
/**
* Only use for testing! Never disable integrity protection!
*/
public PgpSignEncryptInputParcel setIntegrityProtected(boolean integrityProtected) {
this.mIntegrityProtected = integrityProtected;
return this;
}
public PgpSignEncryptInputParcel setAddBackupHeader(boolean addBackupHeader) {
this.mAddBackupHeader = addBackupHeader;
return this;
}
public boolean isAddBackupHeader() {
return mAddBackupHeader;
}
public boolean isHiddenRecipients() {
return mHiddenRecipients;
} }
public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() { public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() {

View File

@@ -20,6 +20,7 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import android.content.Context; import android.content.Context;
import android.net.Uri;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@@ -39,16 +40,19 @@ import org.bouncycastle.openpgp.operator.jcajce.PGPUtil;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation; import org.sufficientlysecure.keychain.operations.BaseOperation;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
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;
@@ -57,7 +61,9 @@ import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
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.InputStreamReader; import java.io.InputStreamReader;
@@ -83,7 +89,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @see org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult * @see org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult
* @see org.sufficientlysecure.keychain.operations.SignEncryptOperation * @see org.sufficientlysecure.keychain.operations.SignEncryptOperation
*/ */
public class PgpSignEncryptOperation extends BaseOperation { public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputParcel> {
private static byte[] NEW_LINE; private static byte[] NEW_LINE;
@@ -105,16 +111,65 @@ public class PgpSignEncryptOperation extends BaseOperation {
@NonNull @NonNull
@Override @Override
// TODO this is horrible, refactor ASAP!! public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput) {
public OperationResult execute(Parcelable input, CryptoInputParcel cryptoInput) { OperationLog log = new OperationLog();
return null;
InputData inputData;
{
if (input.getInputBytes() != null) {
log.add(LogType.MSG_PSE_INPUT_BYTES, 1);
InputStream is = new ByteArrayInputStream(input.getInputBytes());
inputData = new InputData(is, input.getInputBytes().length);
} else {
log.add(LogType.MSG_PSE_INPUT_URI, 1);
Uri uri = input.getInputUri();
try {
InputStream is = FileHelper.openInputStreamSafe(mContext.getContentResolver(), uri);
long fileSize = FileHelper.getFileSize(mContext, uri, 0);
String filename = FileHelper.getFilename(mContext, uri);
inputData = new InputData(is, fileSize, filename);
} catch (FileNotFoundException e) {
log.add(LogType.MSG_PSE_ERROR_INPUT_URI_NOT_FOUND, 1);
return new PgpSignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
}
}
}
OutputStream outStream;
{
if (input.getOutputUri() != null) {
try {
Uri outputUri = input.getOutputUri();
outStream = mContext.getContentResolver().openOutputStream(outputUri);
} catch (FileNotFoundException e) {
log.add(LogType.MSG_PSE_ERROR_OUTPUT_URI_NOT_FOUND, 1);
return new PgpSignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
}
} else {
outStream = new ByteArrayOutputStream();
}
}
PgpSignEncryptResult result = executeInternal(input, cryptoInput, inputData, outStream);
if (outStream instanceof ByteArrayOutputStream) {
byte[] outputData = ((ByteArrayOutputStream) outStream).toByteArray();
result.setOutputBytes(outputData);
}
return result;
}
@NonNull
public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
return executeInternal(input, cryptoInput, inputData, outputStream);
} }
/** /**
* Signs and/or encrypts data based on parameters of class * Signs and/or encrypts data based on parameters of class
*/ */
public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput, private PgpSignEncryptResult executeInternal(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) { InputData inputData, OutputStream outputStream) {
int indent = 0; int indent = 0;
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
@@ -122,36 +177,37 @@ public class PgpSignEncryptOperation extends BaseOperation {
log.add(LogType.MSG_PSE, indent); log.add(LogType.MSG_PSE, indent);
indent += 1; indent += 1;
boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none; PgpSignEncryptData data = input.getData();
boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0) boolean enableSignature = data.getSignatureMasterKeyId() != Constants.key.none;
|| input.getSymmetricPassphrase() != null); boolean enableEncryption = ((data.getEncryptionMasterKeyIds() != null && data.getEncryptionMasterKeyIds().length > 0)
boolean enableCompression = (input.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED); || data.getSymmetricPassphrase() != null);
boolean enableCompression = (data.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED);
Log.d(Constants.TAG, "enableSignature:" + enableSignature Log.d(Constants.TAG, "enableSignature:" + enableSignature
+ "\nenableEncryption:" + enableEncryption + "\nenableEncryption:" + enableEncryption
+ "\nenableCompression:" + enableCompression + "\nenableCompression:" + enableCompression
+ "\nenableAsciiArmorOutput:" + input.isEnableAsciiArmorOutput() + "\nenableAsciiArmorOutput:" + data.isEnableAsciiArmorOutput()
+ "\nisHiddenRecipients:" + input.isHiddenRecipients()); + "\nisHiddenRecipients:" + data.isHiddenRecipients());
// add additional key id to encryption ids (mostly to do self-encryption) // add additional key id to encryption ids (mostly to do self-encryption)
if (enableEncryption && input.getAdditionalEncryptId() != Constants.key.none) { if (enableEncryption && data.getAdditionalEncryptId() != Constants.key.none) {
input.setEncryptionMasterKeyIds(Arrays.copyOf(input.getEncryptionMasterKeyIds(), input.getEncryptionMasterKeyIds().length + 1)); data.setEncryptionMasterKeyIds(Arrays.copyOf(data.getEncryptionMasterKeyIds(), data.getEncryptionMasterKeyIds().length + 1));
input.getEncryptionMasterKeyIds()[input.getEncryptionMasterKeyIds().length - 1] = input.getAdditionalEncryptId(); data.getEncryptionMasterKeyIds()[data.getEncryptionMasterKeyIds().length - 1] = data.getAdditionalEncryptId();
} }
ArmoredOutputStream armorOut = null; ArmoredOutputStream armorOut = null;
OutputStream out; OutputStream out;
if (input.isEnableAsciiArmorOutput()) { if (data.isEnableAsciiArmorOutput()) {
armorOut = new ArmoredOutputStream(new BufferedOutputStream(outputStream, 1 << 16)); armorOut = new ArmoredOutputStream(new BufferedOutputStream(outputStream, 1 << 16));
if (input.getVersionHeader() != null) { if (data.getVersionHeader() != null) {
armorOut.setHeader("Version", input.getVersionHeader()); armorOut.setHeader("Version", data.getVersionHeader());
} }
// if we have a charset, put it in the header // if we have a charset, put it in the header
if (input.getCharset() != null) { if (data.getCharset() != null) {
armorOut.setHeader("Charset", input.getCharset()); armorOut.setHeader("Charset", data.getCharset());
} }
// add proprietary header to indicate that this is a key backup // add proprietary header to indicate that this is a key backup
if (input.isAddBackupHeader()) { if (data.isAddBackupHeader()) {
armorOut.setHeader("BackupVersion", "2"); armorOut.setHeader("BackupVersion", "2");
} }
out = armorOut; out = armorOut;
@@ -166,12 +222,12 @@ public class PgpSignEncryptOperation extends BaseOperation {
updateProgress(R.string.progress_extracting_signature_key, 0, 100); updateProgress(R.string.progress_extracting_signature_key, 0, 100);
try { try {
long signingMasterKeyId = input.getSignatureMasterKeyId(); long signingMasterKeyId = data.getSignatureMasterKeyId();
long signingSubKeyId = input.getSignatureSubKeyId(); long signingSubKeyId = data.getSignatureSubKeyId();
CanonicalizedSecretKeyRing signingKeyRing = CanonicalizedSecretKeyRing signingKeyRing =
mProviderHelper.getCanonicalizedSecretKeyRing(signingMasterKeyId); mProviderHelper.getCanonicalizedSecretKeyRing(signingMasterKeyId);
signingKey = signingKeyRing.getSecretKey(input.getSignatureSubKeyId()); signingKey = signingKeyRing.getSecretKey(data.getSignatureSubKeyId());
// Make sure key is not expired or revoked // Make sure key is not expired or revoked
@@ -240,9 +296,9 @@ public class PgpSignEncryptOperation extends BaseOperation {
} }
// Use requested hash algo // Use requested hash algo
int requestedAlgorithm = input.getSignatureHashAlgorithm(); int requestedAlgorithm = data.getSignatureHashAlgorithm();
if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) { if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
input.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM); data.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
} }
} }
updateProgress(R.string.progress_preparing_streams, 2, 100); updateProgress(R.string.progress_preparing_streams, 2, 100);
@@ -252,36 +308,36 @@ public class PgpSignEncryptOperation extends BaseOperation {
if (enableEncryption) { if (enableEncryption) {
// Use requested encryption algo // Use requested encryption algo
int algo = input.getSymmetricEncryptionAlgorithm(); int algo = data.getSymmetricEncryptionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) { if (algo == PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM; algo = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
} }
JcePGPDataEncryptorBuilder encryptorBuilder = JcePGPDataEncryptorBuilder encryptorBuilder =
new JcePGPDataEncryptorBuilder(algo) new JcePGPDataEncryptorBuilder(algo)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
.setWithIntegrityPacket(input.isIntegrityProtected()); .setWithIntegrityPacket(data.isIntegrityProtected());
cPk = new PGPEncryptedDataGenerator(encryptorBuilder); cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
if (input.getSymmetricPassphrase() != null) { if (data.getSymmetricPassphrase() != null) {
// Symmetric encryption // Symmetric encryption
log.add(LogType.MSG_PSE_SYMMETRIC, indent); log.add(LogType.MSG_PSE_SYMMETRIC, indent);
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().getCharArray()); new JcePBEKeyEncryptionMethodGenerator(data.getSymmetricPassphrase().getCharArray());
cPk.addMethod(symmetricEncryptionGenerator); cPk.addMethod(symmetricEncryptionGenerator);
} else { } else {
log.add(LogType.MSG_PSE_ASYMMETRIC, indent); log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
// Asymmetric encryption // Asymmetric encryption
for (long id : input.getEncryptionMasterKeyIds()) { for (long id : data.getEncryptionMasterKeyIds()) {
try { try {
CanonicalizedPublicKeyRing keyRing = mProviderHelper.getCanonicalizedPublicKeyRing( CanonicalizedPublicKeyRing keyRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingUri(id)); KeyRings.buildUnifiedKeyRingUri(id));
Set<Long> encryptSubKeyIds = keyRing.getEncryptIds(); Set<Long> encryptSubKeyIds = keyRing.getEncryptIds();
for (Long subKeyId : encryptSubKeyIds) { for (Long subKeyId : encryptSubKeyIds) {
CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId); CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId);
cPk.addMethod(key.getPubKeyEncryptionGenerator(input.isHiddenRecipients())); cPk.addMethod(key.getPubKeyEncryptionGenerator(data.isHiddenRecipients()));
log.add(LogType.MSG_PSE_KEY_OK, indent + 1, log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(subKeyId)); KeyFormattingUtils.convertKeyIdToHex(subKeyId));
} }
@@ -310,9 +366,9 @@ public class PgpSignEncryptOperation extends BaseOperation {
updateProgress(R.string.progress_preparing_signature, 4, 100); updateProgress(R.string.progress_preparing_signature, 4, 100);
try { try {
boolean cleartext = input.isCleartextSignature() && input.isEnableAsciiArmorOutput() && !enableEncryption; boolean cleartext = data.isCleartextSignature() && data.isEnableAsciiArmorOutput() && !enableEncryption;
signatureGenerator = signingKey.getDataSignatureGenerator( signatureGenerator = signingKey.getDataSignatureGenerator(
input.getSignatureHashAlgorithm(), cleartext, data.getSignatureHashAlgorithm(), cleartext,
cryptoInput.getCryptoData(), cryptoInput.getSignatureTime()); cryptoInput.getCryptoData(), cryptoInput.getSignatureTime());
} catch (PgpGeneralException e) { } catch (PgpGeneralException e) {
log.add(LogType.MSG_PSE_ERROR_NFC, indent); log.add(LogType.MSG_PSE_ERROR_NFC, indent);
@@ -351,7 +407,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
log.add(LogType.MSG_PSE_COMPRESSING, indent); log.add(LogType.MSG_PSE_COMPRESSING, indent);
// Use preferred compression algo // Use preferred compression algo
int algo = input.getCompressionAlgorithm(); int algo = data.getCompressionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) { if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM; algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
} }
@@ -367,7 +423,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
char literalDataFormatTag; char literalDataFormatTag;
if (input.isCleartextSignature()) { if (data.isCleartextSignature()) {
literalDataFormatTag = PGPLiteralData.UTF8; literalDataFormatTag = PGPLiteralData.UTF8;
} else { } else {
literalDataFormatTag = PGPLiteralData.BINARY; literalDataFormatTag = PGPLiteralData.BINARY;
@@ -397,14 +453,14 @@ public class PgpSignEncryptOperation extends BaseOperation {
literalGen.close(); literalGen.close();
indent -= 1; indent -= 1;
} else if (enableSignature && input.isCleartextSignature() && input.isEnableAsciiArmorOutput()) { } else if (enableSignature && data.isCleartextSignature() && data.isEnableAsciiArmorOutput()) {
/* cleartext signature: sign-only of ascii text */ /* cleartext signature: sign-only of ascii text */
updateProgress(R.string.progress_signing, 8, 100); updateProgress(R.string.progress_signing, 8, 100);
log.add(LogType.MSG_PSE_SIGNING_CLEARTEXT, indent); log.add(LogType.MSG_PSE_SIGNING_CLEARTEXT, indent);
// write -----BEGIN PGP SIGNED MESSAGE----- // write -----BEGIN PGP SIGNED MESSAGE-----
armorOut.beginClearText(input.getSignatureHashAlgorithm()); armorOut.beginClearText(data.getSignatureHashAlgorithm());
InputStream in = new BufferedInputStream(inputData.getInputStream()); InputStream in = new BufferedInputStream(inputData.getInputStream());
final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
@@ -432,7 +488,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
armorOut.endClearText(); armorOut.endClearText();
pOut = new BCPGOutputStream(armorOut); pOut = new BCPGOutputStream(armorOut);
} else if (enableSignature && input.isDetachedSignature()) { } else if (enableSignature && data.isDetachedSignature()) {
/* detached signature */ /* detached signature */
updateProgress(R.string.progress_signing, 8, 100); updateProgress(R.string.progress_signing, 8, 100);
@@ -443,10 +499,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
// handle output stream separately for detached signatures // handle output stream separately for detached signatures
detachedByteOut = new ByteArrayOutputStream(); detachedByteOut = new ByteArrayOutputStream();
OutputStream detachedOut = detachedByteOut; OutputStream detachedOut = detachedByteOut;
if (input.isEnableAsciiArmorOutput()) { if (data.isEnableAsciiArmorOutput()) {
detachedArmorOut = new ArmoredOutputStream(new BufferedOutputStream(detachedOut, 1 << 16)); detachedArmorOut = new ArmoredOutputStream(new BufferedOutputStream(detachedOut, 1 << 16));
if (input.getVersionHeader() != null) { if (data.getVersionHeader() != null) {
detachedArmorOut.setHeader("Version", input.getVersionHeader()); detachedArmorOut.setHeader("Version", data.getVersionHeader());
} }
detachedOut = detachedArmorOut; detachedOut = detachedArmorOut;
@@ -469,7 +525,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
} }
pOut = null; pOut = null;
} else if (enableSignature && !input.isCleartextSignature() && !input.isDetachedSignature()) { } else if (enableSignature && !data.isCleartextSignature() && !data.isDetachedSignature()) {
/* sign-only binary (files/data stream) */ /* sign-only binary (files/data stream) */
updateProgress(R.string.progress_signing, 8, 100); updateProgress(R.string.progress_signing, 8, 100);
@@ -479,7 +535,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
if (enableCompression) { if (enableCompression) {
// Use preferred compression algo // Use preferred compression algo
int algo = input.getCompressionAlgorithm(); int algo = data.getCompressionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) { if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM; algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
} }
@@ -534,7 +590,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
} }
} }
opTime = System.currentTimeMillis() -startTime; opTime = System.currentTimeMillis() - startTime;
Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f", Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f",
opTime / 1000.0) + "s"); opTime / 1000.0) + "s");
@@ -591,7 +647,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
} }
result.setDetachedSignature(detachedByteOut.toByteArray()); result.setDetachedSignature(detachedByteOut.toByteArray());
try { try {
String digestName = PGPUtil.getDigestName(input.getSignatureHashAlgorithm()); String digestName = PGPUtil.getDigestName(data.getSignatureHashAlgorithm());
// construct micalg parameter according to https://tools.ietf.org/html/rfc3156#section-5 // construct micalg parameter according to https://tools.ietf.org/html/rfc3156#section-5
result.setMicAlgDigestName("pgp-" + digestName.toLowerCase()); result.setMicAlgDigestName("pgp-" + digestName.toLowerCase());
} catch (PGPException e) { } catch (PGPException e) {

View File

@@ -20,41 +20,43 @@ package org.sufficientlysecure.keychain.pgp;
import android.net.Uri; import android.net.Uri;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
/** This parcel stores the input of one or more PgpSignEncrypt operations. /**
* This parcel stores the input of one or more PgpSignEncrypt operations.
* All operations will use the same general paramters, differing only in * All operations will use the same general paramters, differing only in
* input and output. Each input/output set depends on the paramters: * input and output. Each input/output set depends on the paramters:
* * <p/>
* - Each input uri is individually encrypted/signed * - Each input uri is individually encrypted/signed
* - If a byte array is supplied, it is treated as an input before uris are processed * - If a byte array is supplied, it is treated as an input before uris are processed
* - The number of output uris must match the number of input uris, plus one more * - The number of output uris must match the number of input uris, plus one more
* if there is a byte array present. * if there is a byte array present.
* - Once the output uris are empty, there must be exactly one input (uri xor bytes) * - Once the output uris are empty, there must be exactly one input (uri xor bytes)
* left, which will be returned in a byte array as part of the result parcel. * left, which will be returned in a byte array as part of the result parcel.
*
*/ */
public class SignEncryptParcel extends PgpSignEncryptInputParcel { public class SignEncryptParcel implements Parcelable {
private PgpSignEncryptData data;
public ArrayList<Uri> mInputUris = new ArrayList<>(); public ArrayList<Uri> mInputUris = new ArrayList<>();
public ArrayList<Uri> mOutputUris = new ArrayList<>(); public ArrayList<Uri> mOutputUris = new ArrayList<>();
public byte[] mBytes; public byte[] mBytes;
public SignEncryptParcel() { public SignEncryptParcel(PgpSignEncryptData data) {
super(); this.data = data;
} }
public SignEncryptParcel(Parcel src) { public SignEncryptParcel(Parcel src) {
super(src);
mInputUris = src.createTypedArrayList(Uri.CREATOR); mInputUris = src.createTypedArrayList(Uri.CREATOR);
mOutputUris = src.createTypedArrayList(Uri.CREATOR); mOutputUris = src.createTypedArrayList(Uri.CREATOR);
mBytes = src.createByteArray(); mBytes = src.createByteArray();
data = src.readParcelable(getClass().getClassLoader());
} }
public boolean isIncomplete() { public boolean isIncomplete() {
@@ -85,17 +87,25 @@ public class SignEncryptParcel extends PgpSignEncryptInputParcel {
mOutputUris.addAll(outputUris); mOutputUris.addAll(outputUris);
} }
public void setData(PgpSignEncryptData data) {
this.data = data;
}
public PgpSignEncryptData getData() {
return data;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
} }
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeTypedList(mInputUris); dest.writeTypedList(mInputUris);
dest.writeTypedList(mOutputUris); dest.writeTypedList(mOutputUris);
dest.writeByteArray(mBytes); dest.writeByteArray(mBytes);
dest.writeParcelable(data, 0);
} }
public static final Creator<SignEncryptParcel> CREATOR = new Creator<SignEncryptParcel>() { public static final Creator<SignEncryptParcel> CREATOR = new Creator<SignEncryptParcel>() {

View File

@@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing.UserId;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
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;
@@ -199,13 +200,14 @@ public class OpenPgpService extends Service {
boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
// sign-only // sign-only
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel() PgpSignEncryptData pgpData = new PgpSignEncryptData();
.setEnableAsciiArmorOutput(asciiArmor) pgpData.setEnableAsciiArmorOutput(asciiArmor)
.setCleartextSignature(cleartextSign) .setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign) .setDetachedSignature(!cleartextSign)
.setVersionHeader(null) .setVersionHeader(null)
.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT); .setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
Intent signKeyIdIntent = getSignKeyMasterId(data); Intent signKeyIdIntent = getSignKeyMasterId(data);
// NOTE: Fallback to return account settings (Old API) // NOTE: Fallback to return account settings (Old API)
if (signKeyIdIntent.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) if (signKeyIdIntent.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)
@@ -217,18 +219,21 @@ public class OpenPgpService extends Service {
if (signKeyId == Constants.key.none) { if (signKeyId == Constants.key.none) {
throw new Exception("No signing key given"); throw new Exception("No signing key given");
} else { } else {
pseInput.setSignatureMasterKeyId(signKeyId); pgpData.setSignatureMasterKeyId(signKeyId);
// get first usable subkey capable of signing // get first usable subkey capable of signing
try { try {
long signSubKeyId = mProviderHelper.getCachedPublicKeyRing( long signSubKeyId = mProviderHelper.getCachedPublicKeyRing(
pseInput.getSignatureMasterKeyId()).getSecretSignId(); pgpData.getSignatureMasterKeyId()).getSecretSignId();
pseInput.setSignatureSubKeyId(signSubKeyId); pgpData.setSignatureSubKeyId(signSubKeyId);
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
throw new Exception("signing subkey not found!", e); throw new Exception("signing subkey not found!", e);
} }
} }
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
// Get Input- and OutputStream from ParcelFileDescriptor // Get Input- and OutputStream from ParcelFileDescriptor
if (!cleartextSign) { if (!cleartextSign) {
// output stream only needed for cleartext signatures, // output stream only needed for cleartext signatures,
@@ -335,8 +340,8 @@ public class OpenPgpService extends Service {
long inputLength = inputStream.available(); long inputLength = inputStream.available();
InputData inputData = new InputData(inputStream, inputLength, originalFilename); InputData inputData = new InputData(inputStream, inputLength, originalFilename);
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(); PgpSignEncryptData pgpData = new PgpSignEncryptData();
pseInput.setEnableAsciiArmorOutput(asciiArmor) pgpData.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null) .setVersionHeader(null)
.setCompressionAlgorithm(compressionId) .setCompressionAlgorithm(compressionId)
.setSymmetricEncryptionAlgorithm(PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) .setSymmetricEncryptionAlgorithm(PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT)
@@ -354,20 +359,20 @@ public class OpenPgpService extends Service {
if (signKeyId == Constants.key.none) { if (signKeyId == Constants.key.none) {
throw new Exception("No signing key given"); throw new Exception("No signing key given");
} else { } else {
pseInput.setSignatureMasterKeyId(signKeyId); pgpData.setSignatureMasterKeyId(signKeyId);
// get first usable subkey capable of signing // get first usable subkey capable of signing
try { try {
long signSubKeyId = mProviderHelper.getCachedPublicKeyRing( long signSubKeyId = mProviderHelper.getCachedPublicKeyRing(
pseInput.getSignatureMasterKeyId()).getSecretSignId(); pgpData.getSignatureMasterKeyId()).getSecretSignId();
pseInput.setSignatureSubKeyId(signSubKeyId); pgpData.setSignatureSubKeyId(signSubKeyId);
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
throw new Exception("signing subkey not found!", e); throw new Exception("signing subkey not found!", e);
} }
} }
// sign and encrypt // sign and encrypt
pseInput.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) pgpData.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT)
.setAdditionalEncryptId(signKeyId); // add sign key for encryption .setAdditionalEncryptId(signKeyId); // add sign key for encryption
} }
@@ -382,9 +387,11 @@ public class OpenPgpService extends Service {
if (accSettings == null || (accSettings.getKeyId() == Constants.key.none)) { if (accSettings == null || (accSettings.getKeyId() == Constants.key.none)) {
return mApiPermissionHelper.getCreateAccountIntent(data, accName); return mApiPermissionHelper.getCreateAccountIntent(data, accName);
} }
pseInput.setAdditionalEncryptId(accSettings.getKeyId()); pgpData.setAdditionalEncryptId(accSettings.getKeyId());
} }
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data); CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (inputParcel == null) { if (inputParcel == null) {
inputParcel = new CryptoInputParcel(new Date()); inputParcel = new CryptoInputParcel(new Date());

View File

@@ -63,6 +63,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider; import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@@ -620,9 +621,7 @@ public class EncryptFilesFragment
} }
// fill values for this action // fill values for this action
SignEncryptParcel data = new SignEncryptParcel(); PgpSignEncryptData data = new PgpSignEncryptData();
data.addInputUris(mFilesAdapter.getAsArrayList());
if (mUseCompression) { if (mUseCompression) {
data.setCompressionAlgorithm( data.setCompressionAlgorithm(
@@ -673,7 +672,11 @@ public class EncryptFilesFragment
data.setSymmetricPassphrase(passphrase); data.setSymmetricPassphrase(passphrase);
} }
return data;
SignEncryptParcel parcel = new SignEncryptParcel(data);
parcel.addInputUris(mFilesAdapter.getAsArrayList());
return parcel;
} }
private Intent createSendIntent() { private Intent createSendIntent() {

View File

@@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment; import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
@@ -230,9 +231,8 @@ public class EncryptTextFragment
} }
// fill values for this action // fill values for this action
SignEncryptParcel data = new SignEncryptParcel(); PgpSignEncryptData data = new PgpSignEncryptData();
data.setBytes(mMessage.getBytes());
data.setCleartextSignature(true); data.setCleartextSignature(true);
if (mUseCompression) { if (mUseCompression) {
@@ -283,7 +283,11 @@ public class EncryptTextFragment
} }
data.setSymmetricPassphrase(passphrase); data.setSymmetricPassphrase(passphrase);
} }
return data;
SignEncryptParcel parcel = new SignEncryptParcel(data);
parcel.setBytes(mMessage.getBytes());
return parcel;
} }
private void copyToClipboard(SignEncryptResult result) { private void copyToClipboard(SignEncryptResult result) {

View File

@@ -180,11 +180,12 @@ public class PgpEncryptDecryptTest {
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(); PgpSignEncryptData pgpData = new PgpSignEncryptData();
b.setSymmetricPassphrase(mSymmetricPassphrase); pgpData.setSymmetricPassphrase(mSymmetricPassphrase);
b.setSymmetricEncryptionAlgorithm( pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()),
data, out); data, out);
@@ -303,13 +304,15 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
PgpSignEncryptData pgpData = new PgpSignEncryptData();
// only sign, and not as cleartext // only sign, and not as cleartext
input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId()); pgpData.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1)); pgpData.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
input.setCleartextSignature(false); pgpData.setCleartextSignature(false);
input.setDetachedSignature(false); pgpData.setDetachedSignature(false);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out); PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
Assert.assertTrue("signing must succeed", result.success()); Assert.assertTrue("signing must succeed", result.success());
@@ -357,14 +360,16 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
PgpSignEncryptData pgpData = new PgpSignEncryptData();
// only sign, as cleartext // only sign, as cleartext
input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId()); pgpData.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1)); pgpData.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
input.setCleartextSignature(true); pgpData.setCleartextSignature(true);
input.setEnableAsciiArmorOutput(true); pgpData.setEnableAsciiArmorOutput(true);
input.setDetachedSignature(false); pgpData.setDetachedSignature(false);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out); PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
Assert.assertTrue("signing must succeed", result.success()); Assert.assertTrue("signing must succeed", result.success());
@@ -417,12 +422,14 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
PgpSignEncryptData pgpData = new PgpSignEncryptData();
// only sign, as cleartext // only sign, as cleartext
input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId()); pgpData.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1)); pgpData.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
input.setDetachedSignature(true); pgpData.setDetachedSignature(true);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out); PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
Assert.assertTrue("signing must succeed", result.success()); Assert.assertTrue("signing must succeed", result.success());
@@ -472,11 +479,14 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
input.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() }); PgpSignEncryptData pgpData = new PgpSignEncryptData();
input.setSymmetricEncryptionAlgorithm( pgpData.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -572,11 +582,14 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
input.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() }); PgpSignEncryptData pgpData = new PgpSignEncryptData();
input.setSymmetricEncryptionAlgorithm( pgpData.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -679,11 +692,14 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
input.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() }); PgpSignEncryptData pgpData = new PgpSignEncryptData();
input.setSymmetricEncryptionAlgorithm( pgpData.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -722,14 +738,16 @@ public class PgpEncryptDecryptTest {
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(); PgpSignEncryptData pgpData = new PgpSignEncryptData();
b.setEncryptionMasterKeyIds(new long[] { pgpData.setEncryptionMasterKeyIds(new long[] {
mStaticRing1.getMasterKeyId(), mStaticRing1.getMasterKeyId(),
mStaticRing2.getMasterKeyId() mStaticRing2.getMasterKeyId()
}); });
b.setSymmetricEncryptionAlgorithm( pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -848,17 +866,19 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
b.setEncryptionMasterKeyIds(new long[] { PgpSignEncryptData pgpData = new PgpSignEncryptData();
pgpData.setEncryptionMasterKeyIds(new long[] {
mStaticRing1.getMasterKeyId(), mStaticRing1.getMasterKeyId(),
mStaticRing2.getMasterKeyId() mStaticRing2.getMasterKeyId()
}); });
b.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId()); pgpData.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
b.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1)); pgpData.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
b.setSymmetricEncryptionAlgorithm( pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(b, PgpSignEncryptResult result = op.execute(b,
new CryptoInputParcel(new Date(), mKeyPhrase1), data, out); new CryptoInputParcel(new Date(), mKeyPhrase1), data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -933,14 +953,17 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
b.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() }); PgpSignEncryptData pgpData = new PgpSignEncryptData();
b.setSymmetricEncryptionAlgorithm( pgpData.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
pgpData.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128); PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
// this only works with ascii armored output! // this only works with ascii armored output!
b.setEnableAsciiArmorOutput(true); pgpData.setEnableAsciiArmorOutput(true);
b.setCharset("iso-2022-jp"); pgpData.setCharset("iso-2022-jp");
PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());
@@ -1002,11 +1025,14 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(RuntimeEnvironment.application), null); new ProviderHelper(RuntimeEnvironment.application), null);
InputData data = new InputData(in, in.available()); InputData data = new InputData(in, in.available());
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
input.setEncryptionMasterKeyIds(new long[]{key.getMasterKeyId()}) PgpSignEncryptData pgpData = new PgpSignEncryptData();
pgpData.setEncryptionMasterKeyIds(new long[]{key.getMasterKeyId()})
.setSymmetricEncryptionAlgorithm(algorithm) .setSymmetricEncryptionAlgorithm(algorithm)
.setIntegrityProtected(isIntegrityProtected); .setIntegrityProtected(isIntegrityProtected);
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData);
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()),
data, out); data, out);
Assert.assertTrue("encryption must succeed", result.success()); Assert.assertTrue("encryption must succeed", result.success());