diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2015-02-02 17:19:31 +0100 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2015-02-02 17:19:31 +0100 |
commit | c763ea35035be678bedacea13ec4c2b7c51f9943 (patch) | |
tree | 12df989068b08859cc2f4a282a3dad473813fabd /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp | |
parent | 95e534e1f5c8494d745b6fec016b21b754fa108e (diff) | |
parent | d125149bf77769c45c9c896e4475b04ed444e5cd (diff) | |
download | open-keychain-c763ea35035be678bedacea13ec4c2b7c51f9943.tar.gz open-keychain-c763ea35035be678bedacea13ec4c2b7c51f9943.tar.bz2 open-keychain-c763ea35035be678bedacea13ec4c2b7c51f9943.zip |
Merge branch 'development' of github.com:open-keychain/open-keychain into development
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java | 8 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java | 2 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java | 176 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java) | 428 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java | 135 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 2 | ||||
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java | 1 |
7 files changed, 458 insertions, 294 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index a69c5fe36..ad9b1900e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -39,7 +39,6 @@ import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; -import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; @@ -47,12 +46,12 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFac import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.BaseOperation; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -616,6 +615,7 @@ public class PgpDecryptVerify extends BaseOperation { int length; byte[] buffer = new byte[1 << 16]; while ((length = dataIn.read(buffer)) > 0) { + Log.d(Constants.TAG, "read bytes: " + length); if (mOutStream != null) { mOutStream.write(buffer, 0, length); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index 0a15fd98f..12de2f637 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -24,8 +24,8 @@ import android.content.pm.PackageManager.NameNotFoundException; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; import java.io.File; import java.io.IOException; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java new file mode 100644 index 000000000..9318be006 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java @@ -0,0 +1,176 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.CompressionAlgorithmTags; +import org.sufficientlysecure.keychain.Constants; + +import java.util.Date; + +public class PgpSignEncryptInput { + + protected String mVersionHeader = null; + protected boolean mEnableAsciiArmorOutput = false; + protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; + protected long[] mEncryptionMasterKeyIds = null; + protected String mSymmetricPassphrase = null; + protected int mSymmetricEncryptionAlgorithm = 0; + protected long mSignatureMasterKeyId = Constants.key.none; + protected Long mSignatureSubKeyId = null; + protected int mSignatureHashAlgorithm = 0; + protected String mSignaturePassphrase = null; + protected long mAdditionalEncryptId = Constants.key.none; + protected byte[] mNfcSignedHash = null; + protected Date mNfcCreationTimestamp = null; + protected boolean mFailOnMissingEncryptionKeyIds = false; + protected String mCharset; + protected boolean mCleartextSignature; + protected boolean mDetachedSignature; + + public String getCharset() { + return mCharset; + } + + public void setCharset(String mCharset) { + this.mCharset = mCharset; + } + + public boolean ismFailOnMissingEncryptionKeyIds() { + return mFailOnMissingEncryptionKeyIds; + } + + public Date getNfcCreationTimestamp() { + return mNfcCreationTimestamp; + } + + public byte[] getNfcSignedHash() { + return mNfcSignedHash; + } + + public long getAdditionalEncryptId() { + return mAdditionalEncryptId; + } + + public PgpSignEncryptInput setAdditionalEncryptId(long additionalEncryptId) { + mAdditionalEncryptId = additionalEncryptId; + return this; + } + + public String getSignaturePassphrase() { + return mSignaturePassphrase; + } + + public PgpSignEncryptInput setSignaturePassphrase(String signaturePassphrase) { + mSignaturePassphrase = signaturePassphrase; + return this; + } + + public int getSignatureHashAlgorithm() { + return mSignatureHashAlgorithm; + } + + public PgpSignEncryptInput setSignatureHashAlgorithm(int signatureHashAlgorithm) { + mSignatureHashAlgorithm = signatureHashAlgorithm; + return this; + } + + public Long getSignatureSubKeyId() { + return mSignatureSubKeyId; + } + + public PgpSignEncryptInput setSignatureSubKeyId(long signatureSubKeyId) { + mSignatureSubKeyId = signatureSubKeyId; + return this; + } + + public long getSignatureMasterKeyId() { + return mSignatureMasterKeyId; + } + + public PgpSignEncryptInput setSignatureMasterKeyId(long signatureMasterKeyId) { + mSignatureMasterKeyId = signatureMasterKeyId; + return this; + } + + public int getSymmetricEncryptionAlgorithm() { + return mSymmetricEncryptionAlgorithm; + } + + public PgpSignEncryptInput setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) { + mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm; + return this; + } + + public String getSymmetricPassphrase() { + return mSymmetricPassphrase; + } + + public PgpSignEncryptInput setSymmetricPassphrase(String symmetricPassphrase) { + mSymmetricPassphrase = symmetricPassphrase; + return this; + } + + public long[] getEncryptionMasterKeyIds() { + return mEncryptionMasterKeyIds; + } + + public PgpSignEncryptInput setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) { + mEncryptionMasterKeyIds = encryptionMasterKeyIds; + return this; + } + + public int getCompressionId() { + return mCompressionId; + } + + public PgpSignEncryptInput setCompressionId(int compressionId) { + mCompressionId = compressionId; + return this; + } + + public boolean ismEnableAsciiArmorOutput() { + return mEnableAsciiArmorOutput; + } + + public String getVersionHeader() { + return mVersionHeader; + } + + public PgpSignEncryptInput setVersionHeader(String versionHeader) { + mVersionHeader = versionHeader; + return this; + } + + public PgpSignEncryptInput setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) { + mEnableAsciiArmorOutput = enableAsciiArmorOutput; + return this; + } + + public PgpSignEncryptInput setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) { + mFailOnMissingEncryptionKeyIds = failOnMissingEncryptionKeyIds; + return this; + } + + public PgpSignEncryptInput setNfcState(byte[] signedHash, Date creationTimestamp) { + mNfcSignedHash = signedHash; + mNfcCreationTimestamp = creationTimestamp; + return this; + } + + public PgpSignEncryptInput setCleartextSignature(boolean cleartextSignature) { + this.mCleartextSignature = cleartextSignature; + return this; + } + + public boolean isCleartextSignature() { + return mCleartextSignature; + } + + public PgpSignEncryptInput setDetachedSignature(boolean detachedSignature) { + this.mDetachedSignature = detachedSignature; + return this; + } + + public boolean isDetachedSignature() { + return mDetachedSignature; + } +} + diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 060db96b4..2fa01d241 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -25,6 +25,7 @@ import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.BCPGOutputStream; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.openpgp.PGPCompressedDataGenerator; +import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedDataGenerator; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPLiteralData; @@ -37,13 +38,13 @@ import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.BaseOperation; +import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; +import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; -import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; -import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -60,33 +61,23 @@ import java.security.SignatureException; import java.util.Arrays; import java.util.Date; import java.util.LinkedList; +import java.util.concurrent.atomic.AtomicBoolean; -/** - * This class uses a Builder pattern! +/** This class supports a single, low-level, sign/encrypt operation. + * + * The operation of this class takes an Input- and OutputStream plus a + * PgpSignEncryptInput, and signs and/or encrypts the stream as + * parametrized in the PgpSignEncryptInput object. It returns its status + * and a possible detached signature as a SignEncryptResult. + * + * For a high-level operation based on URIs, see SignEncryptOperation. + * + * @see org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput + * @see org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult + * @see org.sufficientlysecure.keychain.operations.SignEncryptOperation + * */ -public class PgpSignEncrypt extends BaseOperation { - private String mVersionHeader; - private InputData mData; - private OutputStream mOutStream; - - private boolean mEnableAsciiArmorOutput; - private int mCompressionId; - private long[] mEncryptionMasterKeyIds; - private String mSymmetricPassphrase; - private int mSymmetricEncryptionAlgorithm; - private long mSignatureMasterKeyId; - private Long mSignatureSubKeyId; - private int mSignatureHashAlgorithm; - private String mSignaturePassphrase; - private long mAdditionalEncryptId; - private boolean mCleartextSignature; - private boolean mDetachedSignature; - private String mOriginalFilename; - private boolean mFailOnMissingEncryptionKeyIds; - private String mCharset; - - private byte[] mNfcSignedHash = null; - private Date mNfcCreationTimestamp = null; +public class PgpSignEncryptOperation extends BaseOperation { private static byte[] NEW_LINE; @@ -98,253 +89,107 @@ public class PgpSignEncrypt extends BaseOperation { } } - protected PgpSignEncrypt(Builder builder) { - super(builder.mContext, builder.mProviderHelper, builder.mProgressable); - - // private Constructor can only be called from Builder - this.mVersionHeader = builder.mVersionHeader; - this.mData = builder.mData; - this.mOutStream = builder.mOutStream; - - this.mEnableAsciiArmorOutput = builder.mEnableAsciiArmorOutput; - this.mCompressionId = builder.mCompressionId; - this.mEncryptionMasterKeyIds = builder.mEncryptionMasterKeyIds; - this.mSymmetricPassphrase = builder.mSymmetricPassphrase; - this.mSymmetricEncryptionAlgorithm = builder.mSymmetricEncryptionAlgorithm; - this.mSignatureMasterKeyId = builder.mSignatureMasterKeyId; - this.mSignatureSubKeyId = builder.mSignatureSubKeyId; - this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm; - this.mSignaturePassphrase = builder.mSignaturePassphrase; - this.mAdditionalEncryptId = builder.mAdditionalEncryptId; - this.mCleartextSignature = builder.mCleartextSignature; - this.mDetachedSignature = builder.mDetachedSignature; - this.mNfcSignedHash = builder.mNfcSignedHash; - this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp; - this.mOriginalFilename = builder.mOriginalFilename; - this.mFailOnMissingEncryptionKeyIds = builder.mFailOnMissingEncryptionKeyIds; - this.mCharset = builder.mCharset; + public PgpSignEncryptOperation(Context context, ProviderHelper providerHelper, Progressable progressable, AtomicBoolean cancelled) { + super(context, providerHelper, progressable, cancelled); } - public static class Builder { - // mandatory parameter - private Context mContext; - private ProviderHelper mProviderHelper; - private Progressable mProgressable; - private InputData mData; - private OutputStream mOutStream; - - // optional - private String mVersionHeader = null; - private boolean mEnableAsciiArmorOutput = false; - private int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; - private long[] mEncryptionMasterKeyIds = null; - private String mSymmetricPassphrase = null; - private int mSymmetricEncryptionAlgorithm = 0; - private long mSignatureMasterKeyId = Constants.key.none; - private Long mSignatureSubKeyId = null; - private int mSignatureHashAlgorithm = 0; - private String mSignaturePassphrase = null; - private long mAdditionalEncryptId = Constants.key.none; - private boolean mCleartextSignature = false; - private boolean mDetachedSignature = false; - private String mOriginalFilename = ""; - private byte[] mNfcSignedHash = null; - private Date mNfcCreationTimestamp = null; - private boolean mFailOnMissingEncryptionKeyIds = false; - private String mCharset = null; - - public Builder(Context context, ProviderHelper providerHelper, Progressable progressable, - InputData data, OutputStream outStream) { - mContext = context; - mProviderHelper = providerHelper; - mProgressable = progressable; - - mData = data; - mOutStream = outStream; - } - - public Builder setVersionHeader(String versionHeader) { - mVersionHeader = versionHeader; - return this; - } - - public Builder setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) { - mEnableAsciiArmorOutput = enableAsciiArmorOutput; - return this; - } - - public Builder setCompressionId(int compressionId) { - mCompressionId = compressionId; - return this; - } - - public Builder setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) { - mEncryptionMasterKeyIds = encryptionMasterKeyIds; - return this; - } - - public Builder setSymmetricPassphrase(String symmetricPassphrase) { - mSymmetricPassphrase = symmetricPassphrase; - return this; - } - - public Builder setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) { - mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm; - return this; - } - - public Builder setSignatureMasterKeyId(long signatureMasterKeyId) { - mSignatureMasterKeyId = signatureMasterKeyId; - return this; - } - - public Builder setSignatureSubKeyId(long signatureSubKeyId) { - mSignatureSubKeyId = signatureSubKeyId; - return this; - } - - public Builder setSignatureHashAlgorithm(int signatureHashAlgorithm) { - mSignatureHashAlgorithm = signatureHashAlgorithm; - return this; - } - - public Builder setSignaturePassphrase(String signaturePassphrase) { - mSignaturePassphrase = signaturePassphrase; - return this; - } - - public Builder setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) { - mFailOnMissingEncryptionKeyIds = failOnMissingEncryptionKeyIds; - return this; - } - - public Builder setCharset(String charset) { - mCharset = charset; - return this; - } - - /** - * Also encrypt with the signing keyring - * - * @param additionalEncryptId - * @return - */ - public Builder setAdditionalEncryptId(long additionalEncryptId) { - mAdditionalEncryptId = additionalEncryptId; - return this; - } - - public Builder setCleartextSignature(boolean cleartextSignature) { - mCleartextSignature = cleartextSignature; - return this; - } - - public Builder setDetachedSignature(boolean detachedSignature) { - mDetachedSignature = detachedSignature; - return this; - } - - public Builder setOriginalFilename(String originalFilename) { - mOriginalFilename = originalFilename; - return this; - } - - public Builder setNfcState(byte[] signedHash, Date creationTimestamp) { - mNfcSignedHash = signedHash; - mNfcCreationTimestamp = creationTimestamp; - return this; - } - - public PgpSignEncrypt build() { - return new PgpSignEncrypt(this); - } + public PgpSignEncryptOperation(Context context, ProviderHelper providerHelper, Progressable progressable) { + super(context, providerHelper, progressable); } /** * Signs and/or encrypts data based on parameters of class */ - public SignEncryptResult execute() { + public PgpSignEncryptResult execute(PgpSignEncryptInput input, + InputData inputData, OutputStream outputStream) { int indent = 0; OperationLog log = new OperationLog(); - log.add(LogType.MSG_SE, indent); + log.add(LogType.MSG_PSE, indent); indent += 1; - boolean enableSignature = mSignatureMasterKeyId != Constants.key.none; - boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0) - || mSymmetricPassphrase != null); - boolean enableCompression = (mCompressionId != CompressionAlgorithmTags.UNCOMPRESSED); + boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none; + boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0) + || input.getSymmetricPassphrase() != null); + boolean enableCompression = (input.getCompressionId() != CompressionAlgorithmTags.UNCOMPRESSED); Log.d(Constants.TAG, "enableSignature:" + enableSignature + "\nenableEncryption:" + enableEncryption + "\nenableCompression:" + enableCompression - + "\nenableAsciiArmorOutput:" + mEnableAsciiArmorOutput); + + "\nenableAsciiArmorOutput:" + input.ismEnableAsciiArmorOutput()); // add additional key id to encryption ids (mostly to do self-encryption) - if (enableEncryption && mAdditionalEncryptId != Constants.key.none) { - mEncryptionMasterKeyIds = Arrays.copyOf(mEncryptionMasterKeyIds, mEncryptionMasterKeyIds.length + 1); - mEncryptionMasterKeyIds[mEncryptionMasterKeyIds.length - 1] = mAdditionalEncryptId; + if (enableEncryption && input.getAdditionalEncryptId() != Constants.key.none) { + input.setEncryptionMasterKeyIds(Arrays.copyOf(input.getEncryptionMasterKeyIds(), input.getEncryptionMasterKeyIds().length + 1)); + input.getEncryptionMasterKeyIds()[input.getEncryptionMasterKeyIds().length - 1] = input.getAdditionalEncryptId(); } ArmoredOutputStream armorOut = null; OutputStream out; - if (mEnableAsciiArmorOutput) { - armorOut = new ArmoredOutputStream(mOutStream); - if (mVersionHeader != null) { - armorOut.setHeader("Version", mVersionHeader); + if (input.ismEnableAsciiArmorOutput()) { + armorOut = new ArmoredOutputStream(outputStream); + if (input.getVersionHeader() != null) { + armorOut.setHeader("Version", input.getVersionHeader()); } // if we have a charset, put it in the header - if (mCharset != null) { - armorOut.setHeader("Charset", mCharset); + if (input.getCharset() != null) { + armorOut.setHeader("Charset", input.getCharset()); } out = armorOut; } else { - out = mOutStream; + out = outputStream; } /* Get keys for signature generation for later usage */ CanonicalizedSecretKey signingKey = null; - long signKeyId; if (enableSignature) { try { // fetch the indicated master key id (the one whose name we sign in) CanonicalizedSecretKeyRing signingKeyRing = - mProviderHelper.getCanonicalizedSecretKeyRing(mSignatureMasterKeyId); + mProviderHelper.getCanonicalizedSecretKeyRing(input.getSignatureMasterKeyId()); + + long signKeyId; + // use specified signing subkey, or find the one to use + if (input.getSignatureSubKeyId() == null) { + signKeyId = signingKeyRing.getSecretSignId(); + } else { + signKeyId = input.getSignatureSubKeyId(); + } + // fetch the specific subkey to sign with, or just use the master key if none specified - signKeyId = mSignatureSubKeyId != null ? mSignatureSubKeyId : mSignatureMasterKeyId; signingKey = signingKeyRing.getSecretKey(signKeyId); - // make sure it's a signing key alright! - } catch (ProviderHelper.NotFoundException e) { - log.add(LogType.MSG_SE_ERROR_SIGN_KEY, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + + } catch (ProviderHelper.NotFoundException | PgpGeneralException e) { + log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } // Make sure we are allowed to sign here! if (!signingKey.canSign()) { - log.add(LogType.MSG_SE_ERROR_KEY_SIGN, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } // if no passphrase was explicitly set try to get it from the cache service - if (mSignaturePassphrase == null) { + if (input.getSignaturePassphrase() == null) { try { // returns "" if key has no passphrase - mSignaturePassphrase = getCachedPassphrase(signKeyId); + input.setSignaturePassphrase(getCachedPassphrase(signingKey.getKeyId())); // TODO // log.add(LogType.MSG_DC_PASS_CACHED, indent + 1); } catch (PassphraseCacheInterface.NoSecretKeyException e) { // TODO // log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } // if passphrase was not cached, return here indicating that a passphrase is missing! - if (mSignaturePassphrase == null) { - log.add(LogType.MSG_SE_PENDING_PASSPHRASE, indent + 1); - SignEncryptResult result = new SignEncryptResult(SignEncryptResult.RESULT_PENDING_PASSPHRASE, log); - result.setKeyIdPassphraseNeeded(signKeyId); + if (input.getSignaturePassphrase() == null) { + log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); + PgpSignEncryptResult result = new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE, log); + result.setKeyIdPassphraseNeeded(signingKey.getKeyId()); return result; } } @@ -352,20 +197,24 @@ public class PgpSignEncrypt extends BaseOperation { updateProgress(R.string.progress_extracting_signature_key, 0, 100); try { - if (!signingKey.unlock(mSignaturePassphrase)) { - log.add(LogType.MSG_SE_ERROR_BAD_PASSPHRASE, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + if (!signingKey.unlock(input.getSignaturePassphrase())) { + log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } } catch (PgpGeneralException e) { - log.add(LogType.MSG_SE_ERROR_UNLOCK, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } // check if hash algo is supported + int requestedAlgorithm = input.getSignatureHashAlgorithm(); LinkedList<Integer> supported = signingKey.getSupportedHashAlgorithms(); - if (!supported.contains(mSignatureHashAlgorithm)) { + if (requestedAlgorithm == 0) { // get most preferred - mSignatureHashAlgorithm = supported.getLast(); + input.setSignatureHashAlgorithm(supported.getLast()); + } else if (!supported.contains(requestedAlgorithm)) { + log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } } updateProgress(R.string.progress_preparing_streams, 2, 100); @@ -373,44 +222,48 @@ public class PgpSignEncrypt extends BaseOperation { /* Initialize PGPEncryptedDataGenerator for later usage */ PGPEncryptedDataGenerator cPk = null; if (enableEncryption) { + int algo = input.getSymmetricEncryptionAlgorithm(); + if (algo == 0) { + algo = PGPEncryptedData.AES_128; + } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = - new JcePGPDataEncryptorBuilder(mSymmetricEncryptionAlgorithm) + new JcePGPDataEncryptorBuilder(algo) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME) .setWithIntegrityPacket(true); cPk = new PGPEncryptedDataGenerator(encryptorBuilder); - if (mSymmetricPassphrase != null) { + if (input.getSymmetricPassphrase() != null) { // Symmetric encryption - log.add(LogType.MSG_SE_SYMMETRIC, indent); + log.add(LogType.MSG_PSE_SYMMETRIC, indent); JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = - new JcePBEKeyEncryptionMethodGenerator(mSymmetricPassphrase.toCharArray()); + new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().toCharArray()); cPk.addMethod(symmetricEncryptionGenerator); } else { - log.add(LogType.MSG_SE_ASYMMETRIC, indent); + log.add(LogType.MSG_PSE_ASYMMETRIC, indent); // Asymmetric encryption - for (long id : mEncryptionMasterKeyIds) { + for (long id : input.getEncryptionMasterKeyIds()) { try { CanonicalizedPublicKeyRing keyRing = mProviderHelper.getCanonicalizedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(id)); CanonicalizedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); - log.add(LogType.MSG_SE_KEY_OK, indent + 1, + log.add(LogType.MSG_PSE_KEY_OK, indent + 1, KeyFormattingUtils.convertKeyIdToHex(id)); } catch (PgpKeyNotFoundException e) { - log.add(LogType.MSG_SE_KEY_WARN, indent + 1, + log.add(LogType.MSG_PSE_KEY_WARN, indent + 1, KeyFormattingUtils.convertKeyIdToHex(id)); - if (mFailOnMissingEncryptionKeyIds) { - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + if (input.ismFailOnMissingEncryptionKeyIds()) { + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } } catch (ProviderHelper.NotFoundException e) { - log.add(LogType.MSG_SE_KEY_UNKNOWN, indent + 1, + log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1, KeyFormattingUtils.convertKeyIdToHex(id)); - if (mFailOnMissingEncryptionKeyIds) { - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + if (input.ismFailOnMissingEncryptionKeyIds()) { + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } } } @@ -423,12 +276,12 @@ public class PgpSignEncrypt extends BaseOperation { updateProgress(R.string.progress_preparing_signature, 4, 100); try { - boolean cleartext = mCleartextSignature && mEnableAsciiArmorOutput && !enableEncryption; + boolean cleartext = input.isCleartextSignature() && input.ismEnableAsciiArmorOutput() && !enableEncryption; signatureGenerator = signingKey.getSignatureGenerator( - mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp); + input.getSignatureHashAlgorithm(), cleartext, input.getNfcSignedHash(), input.getNfcCreationTimestamp()); } catch (PgpGeneralException e) { - log.add(LogType.MSG_SE_ERROR_NFC, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_NFC, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } } @@ -449,8 +302,8 @@ public class PgpSignEncrypt extends BaseOperation { /* actual encryption */ updateProgress(R.string.progress_encrypting, 8, 100); log.add(enableSignature - ? LogType.MSG_SE_SIGCRYPTING - : LogType.MSG_SE_ENCRYPTING, + ? LogType.MSG_PSE_SIGCRYPTING + : LogType.MSG_PSE_ENCRYPTING, indent ); indent += 1; @@ -458,8 +311,8 @@ public class PgpSignEncrypt extends BaseOperation { encryptionOut = cPk.open(out, new byte[1 << 16]); if (enableCompression) { - log.add(LogType.MSG_SE_COMPRESSING, indent); - compressGen = new PGPCompressedDataGenerator(mCompressionId); + log.add(LogType.MSG_PSE_COMPRESSING, indent); + compressGen = new PGPCompressedDataGenerator(input.getCompressionId()); bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); } else { bcpgOut = new BCPGOutputStream(encryptionOut); @@ -471,18 +324,18 @@ public class PgpSignEncrypt extends BaseOperation { PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); char literalDataFormatTag; - if (mCleartextSignature) { + if (input.isCleartextSignature()) { literalDataFormatTag = PGPLiteralData.UTF8; } else { literalDataFormatTag = PGPLiteralData.BINARY; } - pOut = literalGen.open(bcpgOut, literalDataFormatTag, mOriginalFilename, new Date(), - new byte[1 << 16]); + pOut = literalGen.open(bcpgOut, literalDataFormatTag, + inputData.getOriginalFilename(), new Date(), new byte[1 << 16]); long alreadyWritten = 0; int length; byte[] buffer = new byte[1 << 16]; - InputStream in = mData.getInputStream(); + InputStream in = inputData.getInputStream(); while ((length = in.read(buffer)) > 0) { pOut.write(buffer, 0, length); @@ -492,8 +345,8 @@ public class PgpSignEncrypt extends BaseOperation { } alreadyWritten += length; - if (mData.getSize() > 0) { - long progress = 100 * alreadyWritten / mData.getSize(); + if (inputData.getSize() > 0) { + long progress = 100 * alreadyWritten / inputData.getSize(); progressScaler.setProgress((int) progress, 100); } } @@ -501,16 +354,16 @@ public class PgpSignEncrypt extends BaseOperation { literalGen.close(); indent -= 1; - } else if (enableSignature && mCleartextSignature && mEnableAsciiArmorOutput) { + } else if (enableSignature && input.isCleartextSignature() && input.ismEnableAsciiArmorOutput()) { /* cleartext signature: sign-only of ascii text */ updateProgress(R.string.progress_signing, 8, 100); - log.add(LogType.MSG_SE_SIGNING, indent); + log.add(LogType.MSG_PSE_SIGNING_CLEARTEXT, indent); // write -----BEGIN PGP SIGNED MESSAGE----- - armorOut.beginClearText(mSignatureHashAlgorithm); + armorOut.beginClearText(input.getSignatureHashAlgorithm()); - InputStream in = mData.getInputStream(); + InputStream in = inputData.getInputStream(); final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // update signature buffer with first line @@ -536,21 +389,21 @@ public class PgpSignEncrypt extends BaseOperation { armorOut.endClearText(); pOut = new BCPGOutputStream(armorOut); - } else if (enableSignature && mDetachedSignature) { + } else if (enableSignature && input.isDetachedSignature()) { /* detached signature */ updateProgress(R.string.progress_signing, 8, 100); - log.add(LogType.MSG_SE_SIGNING, indent); + log.add(LogType.MSG_PSE_SIGNING_DETACHED, indent); - InputStream in = mData.getInputStream(); + InputStream in = inputData.getInputStream(); // handle output stream separately for detached signatures detachedByteOut = new ByteArrayOutputStream(); OutputStream detachedOut = detachedByteOut; - if (mEnableAsciiArmorOutput) { + if (input.ismEnableAsciiArmorOutput()) { detachedArmorOut = new ArmoredOutputStream(detachedOut); - if (mVersionHeader != null) { - detachedArmorOut.setHeader("Version", mVersionHeader); + if (input.getVersionHeader() != null) { + detachedArmorOut.setHeader("Version", input.getVersionHeader()); } detachedOut = detachedArmorOut; @@ -566,23 +419,23 @@ public class PgpSignEncrypt extends BaseOperation { signatureGenerator.update(buffer, 0, length); alreadyWritten += length; - if (mData.getSize() > 0) { - long progress = 100 * alreadyWritten / mData.getSize(); + if (inputData.getSize() > 0) { + long progress = 100 * alreadyWritten / inputData.getSize(); progressScaler.setProgress((int) progress, 100); } } pOut = null; - } else if (enableSignature && !mCleartextSignature && !mDetachedSignature) { + } else if (enableSignature && !input.isCleartextSignature() && !input.isDetachedSignature()) { /* sign-only binary (files/data stream) */ updateProgress(R.string.progress_signing, 8, 100); - log.add(LogType.MSG_SE_SIGNING, indent); + log.add(LogType.MSG_PSE_SIGNING, indent); - InputStream in = mData.getInputStream(); + InputStream in = inputData.getInputStream(); if (enableCompression) { - compressGen = new PGPCompressedDataGenerator(mCompressionId); + compressGen = new PGPCompressedDataGenerator(input.getCompressionId()); bcpgOut = new BCPGOutputStream(compressGen.open(out)); } else { bcpgOut = new BCPGOutputStream(out); @@ -591,7 +444,8 @@ public class PgpSignEncrypt extends BaseOperation { signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); - pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), + pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, + inputData.getOriginalFilename(), new Date(), new byte[1 << 16]); long alreadyWritten = 0; @@ -603,8 +457,8 @@ public class PgpSignEncrypt extends BaseOperation { signatureGenerator.update(buffer, 0, length); alreadyWritten += length; - if (mData.getSize() > 0) { - long progress = 100 * alreadyWritten / mData.getSize(); + if (inputData.getSize() > 0) { + long progress = 100 * alreadyWritten / inputData.getSize(); progressScaler.setProgress((int) progress, 100); } } @@ -613,7 +467,7 @@ public class PgpSignEncrypt extends BaseOperation { } else { pOut = null; // TODO: Is this log right? - log.add(LogType.MSG_SE_CLEARSIGN_ONLY, indent); + log.add(LogType.MSG_PSE_CLEARSIGN_ONLY, indent); } if (enableSignature) { @@ -626,12 +480,12 @@ public class PgpSignEncrypt extends BaseOperation { } } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) { // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed - log.add(LogType.MSG_SE_PENDING_NFC, indent); - SignEncryptResult result = - new SignEncryptResult(SignEncryptResult.RESULT_PENDING_NFC, log); + log.add(LogType.MSG_PSE_PENDING_NFC, indent); + PgpSignEncryptResult result = + new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_NFC, log); // Note that the checked key here is the master key, not the signing key // (although these are always the same on Yubikeys) - result.setNfcData(mSignatureSubKeyId, e.hashToSign, e.hashAlgo, e.creationTimestamp, mSignaturePassphrase); + result.setNfcData(input.getSignatureSubKeyId(), e.hashToSign, e.hashAlgo, e.creationTimestamp, input.getSignaturePassphrase()); Log.d(Constants.TAG, "e.hashToSign" + Hex.toHexString(e.hashToSign)); return result; } @@ -661,25 +515,25 @@ public class PgpSignEncrypt extends BaseOperation { if (out != null) { out.close(); } - if (mOutStream != null) { - mOutStream.close(); + if (outputStream != null) { + outputStream.close(); } } catch (SignatureException e) { - log.add(LogType.MSG_SE_ERROR_SIG, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_SIG, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } catch (PGPException e) { - log.add(LogType.MSG_SE_ERROR_PGP, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_PGP, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } catch (IOException e) { - log.add(LogType.MSG_SE_ERROR_IO, indent); - return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); + log.add(LogType.MSG_PSE_ERROR_IO, indent); + return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } updateProgress(R.string.progress_done, 100, 100); - log.add(LogType.MSG_SE_OK, indent); - SignEncryptResult result = new SignEncryptResult(SignEncryptResult.RESULT_OK, log); + log.add(LogType.MSG_PSE_OK, indent); + PgpSignEncryptResult result = new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_OK, log); if (detachedByteOut != null) { try { detachedByteOut.flush(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java new file mode 100644 index 000000000..a4ed33397 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java @@ -0,0 +1,135 @@ +package org.sufficientlysecure.keychain.pgp; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** This parcel stores the input of one or more PgpSignEncrypt operations. + * All operations will use the same general paramters, differing only in + * input and output. Each input/output set depends on the paramters: + * + * - Each input uri is individually encrypted/signed + * - 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 + * if there is a byte array present. + * - 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. + * + */ +public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable { + + public ArrayList<Uri> mInputUris = new ArrayList<>(); + public ArrayList<Uri> mOutputUris = new ArrayList<>(); + public byte[] mBytes; + + public SignEncryptParcel() { + super(); + } + + public SignEncryptParcel(Parcel src) { + + // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable + mVersionHeader = src.readString(); + mEnableAsciiArmorOutput = src.readInt() == 1; + mCompressionId = src.readInt(); + mEncryptionMasterKeyIds = src.createLongArray(); + mSymmetricPassphrase = src.readString(); + mSymmetricEncryptionAlgorithm = src.readInt(); + mSignatureMasterKeyId = src.readLong(); + mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null; + mSignatureHashAlgorithm = src.readInt(); + mSignaturePassphrase = src.readString(); + mAdditionalEncryptId = src.readLong(); + mNfcSignedHash = src.createByteArray(); + mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null; + mFailOnMissingEncryptionKeyIds = src.readInt() == 1; + mCharset = src.readString(); + mCleartextSignature = src.readInt() == 1; + mDetachedSignature = src.readInt() == 1; + + mInputUris = src.createTypedArrayList(Uri.CREATOR); + mOutputUris = src.createTypedArrayList(Uri.CREATOR); + mBytes = src.createByteArray(); + + } + + public byte[] getBytes() { + return mBytes; + } + + public void setBytes(byte[] bytes) { + mBytes = bytes; + } + + public List<Uri> getInputUris() { + return Collections.unmodifiableList(mInputUris); + } + + public void addInputUris(Collection<Uri> inputUris) { + mInputUris.addAll(inputUris); + } + + public List<Uri> getOutputUris() { + return Collections.unmodifiableList(mOutputUris); + } + + public void addOutputUris(ArrayList<Uri> outputUris) { + mOutputUris.addAll(outputUris); + } + + @Override + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mVersionHeader); + dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0); + dest.writeInt(mCompressionId); + dest.writeLongArray(mEncryptionMasterKeyIds); + dest.writeString(mSymmetricPassphrase); + dest.writeInt(mSymmetricEncryptionAlgorithm); + dest.writeLong(mSignatureMasterKeyId); + if (mSignatureSubKeyId != null) { + dest.writeInt(1); + dest.writeLong(mSignatureSubKeyId); + } else { + dest.writeInt(0); + } + dest.writeInt(mSignatureHashAlgorithm); + dest.writeString(mSignaturePassphrase); + dest.writeLong(mAdditionalEncryptId); + dest.writeByteArray(mNfcSignedHash); + if (mNfcCreationTimestamp != null) { + dest.writeInt(1); + dest.writeLong(mNfcCreationTimestamp.getTime()); + } else { + dest.writeInt(0); + } + dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0); + dest.writeString(mCharset); + dest.writeInt(mCleartextSignature ? 1 : 0); + dest.writeInt(mDetachedSignature ? 1 : 0); + + dest.writeTypedList(mInputUris); + dest.writeTypedList(mOutputUris); + dest.writeByteArray(mBytes); + } + + public static final Creator<SignEncryptParcel> CREATOR = new Creator<SignEncryptParcel>() { + public SignEncryptParcel createFromParcel(final Parcel source) { + return new SignEncryptParcel(source); + } + + public SignEncryptParcel[] newArray(final int size) { + return new SignEncryptParcel[size]; + } + }; + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index af85bd878..681aff56d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -35,9 +35,9 @@ import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java index da6d8b287..8e23d36d9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java @@ -32,7 +32,6 @@ import java.io.IOException; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; -import java.util.Arrays; public class WrappedUserAttribute implements Serializable { |