Introduce constants in OpenPgpSignature and DecryptionResult for unsigned/unencrypted content, update API, introduce simple checks for insecure symmetric algos

This commit is contained in:
Dominik Schürmann
2015-07-25 14:32:47 +02:00
parent dc81e0254c
commit 57378be1c0
19 changed files with 430 additions and 279 deletions

4
.gitmodules vendored
View File

@@ -4,11 +4,11 @@
ignore = dirty ignore = dirty
[submodule "extern/openpgp-api-lib"] [submodule "extern/openpgp-api-lib"]
path = extern/openpgp-api-lib path = extern/openpgp-api-lib
url = https://github.com/open-keychain/openpgp-api-lib.git url = https://github.com/open-keychain/openpgp-api.git
ignore = dirty ignore = dirty
[submodule "extern/openkeychain-api-lib"] [submodule "extern/openkeychain-api-lib"]
path = extern/openkeychain-api-lib path = extern/openkeychain-api-lib
url = https://github.com/open-keychain/openkeychain-api-lib.git url = https://github.com/open-keychain/openkeychain-intents.git
ignore = dirty ignore = dirty
[submodule "extern/KeybaseLib"] [submodule "extern/KeybaseLib"]
path = extern/KeybaseLib path = extern/KeybaseLib

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel; import android.os.Parcel;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@@ -31,7 +32,8 @@ public class DecryptVerifyResult extends InputPendingResult {
public static final int RESULT_KEY_DISALLOWED = RESULT_ERROR + 32; public static final int RESULT_KEY_DISALLOWED = RESULT_ERROR + 32;
OpenPgpSignatureResult mSignatureResult; OpenPgpSignatureResult mSignatureResult;
OpenPgpMetadata mDecryptMetadata; OpenPgpDecryptionResult mDecryptionResult;
OpenPgpMetadata mDecryptionMetadata;
// This holds the charset which was specified in the ascii armor, if specified // This holds the charset which was specified in the ascii armor, if specified
// https://tools.ietf.org/html/rfc4880#page56 // https://tools.ietf.org/html/rfc4880#page56
String mCharset; String mCharset;
@@ -52,7 +54,8 @@ public class DecryptVerifyResult extends InputPendingResult {
public DecryptVerifyResult(Parcel source) { public DecryptVerifyResult(Parcel source) {
super(source); super(source);
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader()); mDecryptionResult = source.readParcelable(OpenPgpDecryptionResult.class.getClassLoader());
mDecryptionMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
mCachedCryptoInputParcel = source.readParcelable(CryptoInputParcel.class.getClassLoader()); mCachedCryptoInputParcel = source.readParcelable(CryptoInputParcel.class.getClassLoader());
} }
@@ -69,6 +72,14 @@ public class DecryptVerifyResult extends InputPendingResult {
mSignatureResult = signatureResult; mSignatureResult = signatureResult;
} }
public OpenPgpDecryptionResult getDecryptionResult() {
return mDecryptionResult;
}
public void setDecryptionResult(OpenPgpDecryptionResult decryptionResult) {
mDecryptionResult = decryptionResult;
}
public CryptoInputParcel getCachedCryptoInputParcel() { public CryptoInputParcel getCachedCryptoInputParcel() {
return mCachedCryptoInputParcel; return mCachedCryptoInputParcel;
} }
@@ -77,12 +88,12 @@ public class DecryptVerifyResult extends InputPendingResult {
mCachedCryptoInputParcel = cachedCryptoInputParcel; mCachedCryptoInputParcel = cachedCryptoInputParcel;
} }
public OpenPgpMetadata getDecryptMetadata() { public OpenPgpMetadata getDecryptionMetadata() {
return mDecryptMetadata; return mDecryptionMetadata;
} }
public void setDecryptMetadata(OpenPgpMetadata decryptMetadata) { public void setDecryptionMetadata(OpenPgpMetadata decryptMetadata) {
mDecryptMetadata = decryptMetadata; mDecryptionMetadata = decryptMetadata;
} }
public String getCharset () { public String getCharset () {
@@ -107,9 +118,10 @@ public class DecryptVerifyResult extends InputPendingResult {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags); super.writeToParcel(dest, flags);
dest.writeParcelable(mSignatureResult, 0); dest.writeParcelable(mSignatureResult, flags);
dest.writeParcelable(mDecryptMetadata, 0); dest.writeParcelable(mDecryptionResult, flags);
dest.writeParcelable(mCachedCryptoInputParcel, 0); dest.writeParcelable(mDecryptionMetadata, flags);
dest.writeParcelable(mCachedCryptoInputParcel, flags);
} }
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() { public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {

View File

@@ -184,7 +184,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
// TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS // TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS
// choose best algo // choose best algo
return PgpConstants.sPreferredHashAlgorithms; return new ArrayList<>();
} }
private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo,

View File

@@ -30,7 +30,6 @@ import java.util.ArrayList;
*/ */
public class OpenPgpSignatureResultBuilder { public class OpenPgpSignatureResultBuilder {
// OpenPgpSignatureResult // OpenPgpSignatureResult
private boolean mSignatureOnly = false;
private String mPrimaryUserId; private String mPrimaryUserId;
private ArrayList<String> mUserIds = new ArrayList<>(); private ArrayList<String> mUserIds = new ArrayList<>();
private long mKeyId; private long mKeyId;
@@ -42,10 +41,7 @@ public class OpenPgpSignatureResultBuilder {
private boolean mIsSignatureKeyCertified = false; private boolean mIsSignatureKeyCertified = false;
private boolean mIsKeyRevoked = false; private boolean mIsKeyRevoked = false;
private boolean mIsKeyExpired = false; private boolean mIsKeyExpired = false;
private boolean mInsecure = false;
public void setSignatureOnly(boolean signatureOnly) {
this.mSignatureOnly = signatureOnly;
}
public void setPrimaryUserId(String userId) { public void setPrimaryUserId(String userId) {
this.mPrimaryUserId = userId; this.mPrimaryUserId = userId;
@@ -63,6 +59,10 @@ public class OpenPgpSignatureResultBuilder {
this.mValidSignature = validSignature; this.mValidSignature = validSignature;
} }
public void setInsecure(boolean insecure) {
this.mInsecure = insecure;
}
public void setSignatureKeyCertified(boolean isSignatureKeyCertified) { public void setSignatureKeyCertified(boolean isSignatureKeyCertified) {
this.mIsSignatureKeyCertified = isSignatureKeyCertified; this.mIsSignatureKeyCertified = isSignatureKeyCertified;
} }
@@ -87,6 +87,10 @@ public class OpenPgpSignatureResultBuilder {
return mValidSignature; return mValidSignature;
} }
public boolean isInsecure() {
return mInsecure;
}
public void initValid(CanonicalizedPublicKeyRing signingRing, public void initValid(CanonicalizedPublicKeyRing signingRing,
CanonicalizedPublicKey signingKey) { CanonicalizedPublicKey signingKey) {
setSignatureAvailable(true); setSignatureAvailable(true);
@@ -109,47 +113,50 @@ public class OpenPgpSignatureResultBuilder {
} }
public OpenPgpSignatureResult build() { public OpenPgpSignatureResult build() {
if (mSignatureAvailable) { OpenPgpSignatureResult result = new OpenPgpSignatureResult();
OpenPgpSignatureResult result = new OpenPgpSignatureResult();
result.setSignatureOnly(mSignatureOnly);
// valid sig!
if (mKnownKey) {
if (mValidSignature) {
result.setKeyId(mKeyId);
result.setPrimaryUserId(mPrimaryUserId);
result.setUserIds(mUserIds);
if (mIsKeyRevoked) {
Log.d(Constants.TAG, "SIGNATURE_KEY_REVOKED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED);
} else if (mIsKeyExpired) {
Log.d(Constants.TAG, "SIGNATURE_KEY_EXPIRED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED);
} else if (mIsSignatureKeyCertified) {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED);
} else {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
}
} else {
Log.d(Constants.TAG, "Error! Invalid signature.");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
}
} else {
result.setKeyId(mKeyId);
Log.d(Constants.TAG, "SIGNATURE_KEY_MISSING");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_MISSING);
}
if (!mSignatureAvailable) {
Log.d(Constants.TAG, "RESULT_NO_SIGNATURE");
result.setResult(OpenPgpSignatureResult.RESULT_NO_SIGNATURE);
return result; return result;
} else {
Log.d(Constants.TAG, "no signature found!");
return null;
} }
if (!mKnownKey) {
result.setKeyId(mKeyId);
Log.d(Constants.TAG, "RESULT_KEY_MISSING");
result.setResult(OpenPgpSignatureResult.RESULT_KEY_MISSING);
return result;
}
if (!mValidSignature) {
Log.d(Constants.TAG, "RESULT_INVALID_SIGNATURE");
result.setResult(OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE);
return result;
}
result.setKeyId(mKeyId);
result.setPrimaryUserId(mPrimaryUserId);
result.setUserIds(mUserIds);
if (mIsKeyRevoked) {
Log.d(Constants.TAG, "RESULT_INVALID_KEY_REVOKED");
result.setResult(OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED);
} else if (mIsKeyExpired) {
Log.d(Constants.TAG, "RESULT_INVALID_KEY_EXPIRED");
result.setResult(OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED);
} else if (mInsecure) {
Log.d(Constants.TAG, "RESULT_INVALID_INSECURE");
result.setResult(OpenPgpSignatureResult.RESULT_INVALID_INSECURE);
} else if (mIsSignatureKeyCertified) {
Log.d(Constants.TAG, "RESULT_VALID_CONFIRMED");
result.setResult(OpenPgpSignatureResult.RESULT_VALID_CONFIRMED);
} else {
Log.d(Constants.TAG, "RESULT_VALID_UNCONFIRMED");
result.setResult(OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED);
}
return result;
} }

View File

@@ -21,51 +21,96 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import java.util.ArrayList; import java.util.HashSet;
/**
* NIST requirements for 2011-2030 (http://www.keylength.com/en/4/):
* - RSA: 2048 bit
* - ECC: 224 bit
* - Symmetric: 3TDEA
* - Digital Signature (hash A): SHA-224 - SHA-512
*/
public class PgpConstants { public class PgpConstants {
public static ArrayList<Integer> sPreferredSymmetricAlgorithms = new ArrayList<>(); // public interface MIN_REQUIREMENT {
public static ArrayList<Integer> sPreferredHashAlgorithms = new ArrayList<>(); // int MIN_BITS;
public static ArrayList<Integer> sPreferredCompressionAlgorithms = new ArrayList<>(); // int BINDING_SIGNATURE_HASH_ALGO; // for User IDs, subkeys,...
// int SYMMETRIC_ALGO;
// }
// https://tools.ietf.org/html/rfc6637#section-13
// TODO: use hashmaps for contains in O(1) and intersections!
// PgpDecryptVerify: Secure Algorithms Whitelist
// all other algorithms will be rejected with OpenPgpDecryptionResult.RESULT_INSECURE
public static HashSet<Integer> sSymmetricAlgorithmsWhitelist = new HashSet<>();
static {
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_256);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_192);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_128);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TWOFISH);
}
// all other algorithms will be rejected with OpenPgpSignatureResult.RESULT_INVALID_INSECURE
public static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>();
static {
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA256);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA512);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA384);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA224);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA1);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.RIPEMD160);
}
/* /*
* Most preferred is first * Most preferred is first
* These arrays are written as preferred algorithms into the keys on creation. * These arrays are written as preferred algorithms into the keys on creation.
* Other implementations may choose to honor this selection. * Other implementations may choose to honor this selection.
*
* These lists also define the only algorithms which are used in OpenKeychain.
* We do not support algorithms such as MD5
*/ */
static { public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_256); SymmetricKeyAlgorithmTags.AES_256,
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_192); SymmetricKeyAlgorithmTags.AES_192,
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_128); SymmetricKeyAlgorithmTags.AES_128,
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.TWOFISH); SymmetricKeyAlgorithmTags.TWOFISH
};
// NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?) // NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?)
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA256); public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA512); HashAlgorithmTags.SHA256,
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA384); HashAlgorithmTags.SHA512,
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA224); HashAlgorithmTags.SHA384,
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA1); HashAlgorithmTags.SHA224,
sPreferredHashAlgorithms.add(HashAlgorithmTags.RIPEMD160); };
/* /*
* Prefer ZIP * Prefer ZIP
* "ZLIB provides no benefit over ZIP and is more malleable" * "ZLIB provides no benefit over ZIP and is more malleable"
* - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives") * - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives")
* BZIP2: very slow * BZIP2: very slow
*/ */
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZIP); public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZLIB); CompressionAlgorithmTags.ZIP,
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.BZIP2); CompressionAlgorithmTags.ZLIB,
} CompressionAlgorithmTags.BZIP2
};
public static final int CERTIFY_HASH_ALGO = HashAlgorithmTags.SHA256; public static final int CERTIFY_HASH_ALGO = HashAlgorithmTags.SHA256;
public static final int DEFAULT_SYMMETRIC_ALGORITHM = SymmetricKeyAlgorithmTags.AES_256;
public interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags {
int USE_DEFAULT = -1;
}
public static final int DEFAULT_HASH_ALGORITHM = HashAlgorithmTags.SHA256;
public interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags {
int USE_DEFAULT = -1;
}
public static final int DEFAULT_COMPRESSION_ALGORITHM = CompressionAlgorithmTags.ZIP;
public interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags {
int USE_DEFAULT = -1;
}
/* /*
* Note: s2kcount is a number between 0 and 0xff that controls the * Note: s2kcount is a number between 0 and 0xff that controls the
* number of times to iterate the password hash before use. More * number of times to iterate the password hash before use. More
@@ -87,28 +132,9 @@ public class PgpConstants {
public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90; public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90;
public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256; public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256;
public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256;
public static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; public static final int SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256;
// NOTE: only SHA1 is supported for key checksum calculations in OpenPGP, // NOTE: only SHA1 is supported for key checksum calculations in OpenPGP,
// see http://tools.ietf.org/html/rfc488 0#section-5.5.3 // see http://tools.ietf.org/html/rfc488 0#section-5.5.3
public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1; public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1;
public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags {
public static final int USE_PREFERRED = -1;
}
public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags {
public static final int USE_PREFERRED = -1;
}
public static interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags {
public static final int USE_PREFERRED = -1;
}
public static int[] getAsArray(ArrayList<Integer> list) {
int[] array = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
return array;
}
} }

View File

@@ -22,6 +22,7 @@ import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.ArmoredInputStream;
@@ -283,10 +284,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject(); PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
PGPSignature messageSignature = signatureList.get(signatureIndex); PGPSignature messageSignature = signatureList.get(signatureIndex);
// these are not cleartext signatures!
// TODO: what about binary signatures?
signatureResultBuilder.setSignatureOnly(false);
// Verify signature and check binding signatures // Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature); boolean validSignature = signature.verify(messageSignature);
if (validSignature) { if (validSignature) {
@@ -298,8 +295,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
OpenPgpSignatureResult signatureResult = signatureResultBuilder.build(); OpenPgpSignatureResult signatureResult = signatureResultBuilder.build();
if (signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_CONFIRMED
&& signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED) { && signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED) {
log.add(LogType.MSG_VL_ERROR_INTEGRITY_CHECK, indent); log.add(LogType.MSG_VL_ERROR_INTEGRITY_CHECK, indent);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
} }
@@ -309,9 +306,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_VL_OK, indent); log.add(LogType.MSG_VL_OK, indent);
// Return a positive result, with metadata and verification info // Return a positive result, with metadata and verification info
DecryptVerifyResult result = DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setSignatureResult(signatureResult); result.setSignatureResult(signatureResult);
result.setDecryptionResult(
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
return result; return result;
} }
@@ -322,6 +320,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput, PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
InputStream in, OutputStream out, int indent) throws IOException, PGPException { InputStream in, OutputStream out, int indent) throws IOException, PGPException {
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
OpenPgpDecryptionResult decryptionResult = new OpenPgpDecryptionResult();
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
log.add(LogType.MSG_DC, indent); log.add(LogType.MSG_DC, indent);
@@ -614,15 +614,16 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
} }
decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_ENCRYPTED);
// Warn about old encryption algorithms! // Check for insecure encryption algorithms!
if (!PgpConstants.sPreferredSymmetricAlgorithms.contains(symmetricEncryptionAlgo)) { if (!PgpConstants.sSymmetricAlgorithmsWhitelist.contains(symmetricEncryptionAlgo)) {
log.add(LogType.MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO, indent + 1); log.add(LogType.MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE);
} }
JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear); JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
Object dataChunk = plainFact.nextObject(); Object dataChunk = plainFact.nextObject();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
int signatureIndex = -1; int signatureIndex = -1;
CanonicalizedPublicKeyRing signingRing = null; CanonicalizedPublicKeyRing signingRing = null;
CanonicalizedPublicKey signingKey = null; CanonicalizedPublicKey signingKey = null;
@@ -752,7 +753,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
DecryptVerifyResult result = DecryptVerifyResult result =
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setCharset(charset); result.setCharset(charset);
result.setDecryptMetadata(metadata); result.setDecryptionMetadata(metadata);
return result; return result;
} }
@@ -809,11 +810,9 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject(); PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
PGPSignature messageSignature = signatureList.get(signatureIndex); PGPSignature messageSignature = signatureList.get(signatureIndex);
// these are not cleartext signatures!
// TODO: what about binary signatures? // TODO: what about binary signatures?
signatureResultBuilder.setSignatureOnly(false);
// Verify signature and check binding signatures // Verify signature
boolean validSignature = signature.verify(messageSignature); boolean validSignature = signature.verify(messageSignature);
if (validSignature) { if (validSignature) {
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
@@ -821,10 +820,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
} }
// Don't allow verification of old hash algorithms! // check for insecure hash algorithms
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
validSignature = false;
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setValidSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
@@ -852,7 +851,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
Log.d(Constants.TAG, "MDC fail"); Log.d(Constants.TAG, "MDC fail");
if (!signatureResultBuilder.isValidSignature()) { if (!signatureResultBuilder.isValidSignature()) {
log.add(LogType.MSG_DC_ERROR_INTEGRITY_MISSING, indent); log.add(LogType.MSG_DC_ERROR_INTEGRITY_MISSING, indent);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE);
} }
} }
@@ -861,12 +860,12 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_OK, indent); log.add(LogType.MSG_DC_OK, indent);
// Return a positive result, with metadata and verification info // Return a positive result, with metadata and verification info
DecryptVerifyResult result = DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setCachedCryptoInputParcel(cryptoInput); result.setCachedCryptoInputParcel(cryptoInput);
result.setDecryptMetadata(metadata);
result.setSignatureResult(signatureResultBuilder.build()); result.setSignatureResult(signatureResultBuilder.build());
result.setCharset(charset); result.setCharset(charset);
result.setDecryptionResult(decryptionResult);
result.setDecryptionMetadata(metadata);
return result; return result;
} }
@@ -885,8 +884,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
// cleartext signatures are never encrypted ;)
signatureResultBuilder.setSignatureOnly(true);
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -956,10 +953,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
} }
// Don't allow verification of old hash algorithms! // check for insecure hash algorithms
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
validSignature = false;
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setValidSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
@@ -981,8 +978,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
clearText.length); clearText.length);
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setDecryptMetadata(metadata);
result.setSignatureResult(signatureResultBuilder.build()); result.setSignatureResult(signatureResultBuilder.build());
result.setDecryptionResult(
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
result.setDecryptionMetadata(metadata);
return result; return result;
} }
@@ -994,8 +993,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
// detached signatures are never encrypted
signatureResultBuilder.setSignatureOnly(true);
updateProgress(R.string.progress_processing_signature, 0, 100); updateProgress(R.string.progress_processing_signature, 0, 100);
InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature()); InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature());
@@ -1050,9 +1047,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
updateProgress(R.string.progress_verifying_signature, 90, 100); updateProgress(R.string.progress_verifying_signature, 90, 100);
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
// these are not cleartext signatures!
signatureResultBuilder.setSignatureOnly(false);
// Verify signature and check binding signatures // Verify signature and check binding signatures
boolean validSignature = signature.verify(); boolean validSignature = signature.verify();
if (validSignature) { if (validSignature) {
@@ -1061,10 +1055,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
} }
// Don't allow verification of old hash algorithms! // check for insecure hash algorithms
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
validSignature = false;
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setValidSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
@@ -1076,6 +1070,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setSignatureResult(signatureResultBuilder.build()); result.setSignatureResult(signatureResultBuilder.build());
result.setDecryptionResult(
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
return result; return result;
} }

View File

@@ -1206,7 +1206,7 @@ public class PgpKeyOperation {
// add packet with EMPTY notation data (updates old one, but will be stripped later) // add packet with EMPTY notation data (updates old one, but will be stripped later)
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
{ // set subpackets { // set subpackets
@@ -1233,7 +1233,7 @@ public class PgpKeyOperation {
// add packet with "pin" notation data // add packet with "pin" notation data
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
{ // set subpackets { // set subpackets
@@ -1440,13 +1440,13 @@ public class PgpKeyOperation {
if (divertToCard) { if (divertToCard) {
// use synchronous "NFC based" SignerBuilder // use synchronous "NFC based" SignerBuilder
builder = new NfcSyncPGPContentSignerBuilder( builder = new NfcSyncPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO, pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO,
pKey.getKeyID(), cryptoInput.getCryptoData()) pKey.getKeyID(), cryptoInput.getCryptoData())
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else { } else {
// content signer based on signing key algorithm and chosen hash algorithm // content signer based on signing key algorithm and chosen hash algorithm
builder = new JcaPGPContentSignerBuilder( builder = new JcaPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} }
@@ -1472,11 +1472,11 @@ public class PgpKeyOperation {
*/ */
/* non-critical subpackets: */ /* non-critical subpackets: */
hashedPacketsGen.setPreferredSymmetricAlgorithms(false, hashedPacketsGen.setPreferredSymmetricAlgorithms(false,
PgpConstants.getAsArray(PgpConstants.sPreferredSymmetricAlgorithms)); PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS);
hashedPacketsGen.setPreferredHashAlgorithms(false, hashedPacketsGen.setPreferredHashAlgorithms(false,
PgpConstants.getAsArray(PgpConstants.sPreferredHashAlgorithms)); PgpConstants.PREFERRED_HASH_ALGORITHMS);
hashedPacketsGen.setPreferredCompressionAlgorithms(false, hashedPacketsGen.setPreferredCompressionAlgorithms(false,
PgpConstants.getAsArray(PgpConstants.sPreferredCompressionAlgorithms)); PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS);
hashedPacketsGen.setPrimaryUserID(false, primary); hashedPacketsGen.setPrimaryUserID(false, primary);
/* critical subpackets: we consider those important for a modern pgp implementation */ /* critical subpackets: we consider those important for a modern pgp implementation */

View File

@@ -30,13 +30,13 @@ public class PgpSignEncryptInputParcel implements Parcelable {
protected String mVersionHeader = null; protected String mVersionHeader = null;
protected boolean mEnableAsciiArmorOutput = false; protected boolean mEnableAsciiArmorOutput = false;
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null; protected long[] mEncryptionMasterKeyIds = null;
protected Passphrase mSymmetricPassphrase = null; protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED; protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
protected long mSignatureMasterKeyId = Constants.key.none; protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null; protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED; protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
protected long mAdditionalEncryptId = Constants.key.none; protected long mAdditionalEncryptId = Constants.key.none;
protected boolean mFailOnMissingEncryptionKeyIds = false; protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset; protected String mCharset;
@@ -55,7 +55,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mVersionHeader = source.readString(); mVersionHeader = source.readString();
mEnableAsciiArmorOutput = source.readInt() == 1; mEnableAsciiArmorOutput = source.readInt() == 1;
mCompressionId = source.readInt(); mCompressionAlgorithm = source.readInt();
mEncryptionMasterKeyIds = source.createLongArray(); mEncryptionMasterKeyIds = source.createLongArray();
mSymmetricPassphrase = source.readParcelable(loader); mSymmetricPassphrase = source.readParcelable(loader);
mSymmetricEncryptionAlgorithm = source.readInt(); mSymmetricEncryptionAlgorithm = source.readInt();
@@ -79,7 +79,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mVersionHeader); dest.writeString(mVersionHeader);
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0); dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
dest.writeInt(mCompressionId); dest.writeInt(mCompressionAlgorithm);
dest.writeLongArray(mEncryptionMasterKeyIds); dest.writeLongArray(mEncryptionMasterKeyIds);
dest.writeParcelable(mSymmetricPassphrase, 0); dest.writeParcelable(mSymmetricPassphrase, 0);
dest.writeInt(mSymmetricEncryptionAlgorithm); dest.writeInt(mSymmetricEncryptionAlgorithm);
@@ -174,12 +174,12 @@ public class PgpSignEncryptInputParcel implements Parcelable {
return this; return this;
} }
public int getCompressionId() { public int getCompressionAlgorithm() {
return mCompressionId; return mCompressionAlgorithm;
} }
public PgpSignEncryptInputParcel setCompressionId(int compressionId) { public PgpSignEncryptInputParcel setCompressionAlgorithm(int compressionAlgorithm) {
mCompressionId = compressionId; mCompressionAlgorithm = compressionAlgorithm;
return this; return this;
} }

View File

@@ -124,7 +124,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none; boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none;
boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0) boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0)
|| input.getSymmetricPassphrase() != null); || input.getSymmetricPassphrase() != null);
boolean enableCompression = (input.getCompressionId() != CompressionAlgorithmTags.UNCOMPRESSED); boolean enableCompression = (input.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED);
Log.d(Constants.TAG, "enableSignature:" + enableSignature Log.d(Constants.TAG, "enableSignature:" + enableSignature
+ "\nenableEncryption:" + enableEncryption + "\nenableEncryption:" + enableEncryption
@@ -229,9 +229,11 @@ public class PgpSignEncryptOperation extends BaseOperation {
// Use preferred hash algo // Use preferred hash algo
int requestedAlgorithm = input.getSignatureHashAlgorithm(); int requestedAlgorithm = input.getSignatureHashAlgorithm();
ArrayList<Integer> supported = signingKey.getSupportedHashAlgorithms(); ArrayList<Integer> supported = signingKey.getSupportedHashAlgorithms();
if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
input.setSignatureHashAlgorithm(PgpConstants.DEFAULT_HASH_ALGORITHM);
// TODO
// get most preferred // get most preferred
input.setSignatureHashAlgorithm(supported.get(0)); // input.setSignatureHashAlgorithm(supported.get(0));
} else if (!supported.contains(requestedAlgorithm)) { } else if (!supported.contains(requestedAlgorithm)) {
log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent); log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
@@ -245,10 +247,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
// Use preferred encryption algo // Use preferred encryption algo
int algo = input.getSymmetricEncryptionAlgorithm(); int algo = input.getSymmetricEncryptionAlgorithm();
if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
// get most preferred // get most preferred
// TODO: get from recipients // TODO: get from recipients
algo = PgpConstants.sPreferredSymmetricAlgorithms.get(0); algo = PgpConstants.DEFAULT_SYMMETRIC_ALGORITHM;
} }
// has Integrity packet enabled! // has Integrity packet enabled!
JcePGPDataEncryptorBuilder encryptorBuilder = JcePGPDataEncryptorBuilder encryptorBuilder =
@@ -341,7 +343,13 @@ public class PgpSignEncryptOperation extends BaseOperation {
if (enableCompression) { if (enableCompression) {
log.add(LogType.MSG_PSE_COMPRESSING, indent); log.add(LogType.MSG_PSE_COMPRESSING, indent);
compressGen = new PGPCompressedDataGenerator(input.getCompressionId());
// Use preferred compression algo
int algo = input.getCompressionAlgorithm();
if (algo == PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpConstants.DEFAULT_COMPRESSION_ALGORITHM;
}
compressGen = new PGPCompressedDataGenerator(algo);
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
} else { } else {
bcpgOut = new BCPGOutputStream(encryptionOut); bcpgOut = new BCPGOutputStream(encryptionOut);
@@ -464,7 +472,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
InputStream in = inputData.getInputStream(); InputStream in = inputData.getInputStream();
if (enableCompression) { if (enableCompression) {
compressGen = new PGPCompressedDataGenerator(input.getCompressionId()); compressGen = new PGPCompressedDataGenerator(input.getCompressionAlgorithm());
bcpgOut = new BCPGOutputStream(compressGen.open(out)); bcpgOut = new BCPGOutputStream(compressGen.open(out));
} else { } else {
bcpgOut = new BCPGOutputStream(out); bcpgOut = new BCPGOutputStream(out);

View File

@@ -1434,9 +1434,9 @@ public class ProviderHelper {
// DEPRECATED and thus hardcoded // DEPRECATED and thus hardcoded
values.put(KeychainContract.ApiAccounts.COMPRESSION, CompressionAlgorithmTags.ZLIB); values.put(KeychainContract.ApiAccounts.COMPRESSION, CompressionAlgorithmTags.ZLIB);
values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM,
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, values.put(KeychainContract.ApiAccounts.HASH_ALORITHM,
PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
return values; return values;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,9 +24,11 @@ import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.IBinder; import android.os.IBinder;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
@@ -247,7 +249,7 @@ public class OpenPgpService extends RemoteService {
.setCleartextSignature(cleartextSign) .setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign) .setDetachedSignature(!cleartextSign)
.setVersionHeader(null) .setVersionHeader(null)
.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); .setSignatureHashAlgorithm(PgpConstants.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)
@@ -390,8 +392,8 @@ public class OpenPgpService extends RemoteService {
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(); PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel();
pseInput.setEnableAsciiArmorOutput(asciiArmor) pseInput.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null) .setVersionHeader(null)
.setCompressionId(compressionId) .setCompressionAlgorithm(compressionId)
.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) .setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT)
.setEncryptionMasterKeyIds(keyIds) .setEncryptionMasterKeyIds(keyIds)
.setFailOnMissingEncryptionKeyIds(true); .setFailOnMissingEncryptionKeyIds(true);
@@ -420,7 +422,7 @@ public class OpenPgpService extends RemoteService {
} }
// sign and encrypt // sign and encrypt
pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT)
.setAdditionalEncryptId(signKeyId); // add sign key for encryption .setAdditionalEncryptId(signKeyId); // add sign key for encryption
} }
@@ -540,10 +542,10 @@ public class OpenPgpService extends RemoteService {
// allow only private keys associated with accounts of this app // allow only private keys associated with accounts of this app
// no support for symmetric encryption // no support for symmetric encryption
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel() PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel()
.setAllowSymmetricDecryption(false) .setAllowSymmetricDecryption(false)
.setAllowedKeyIds(allowedKeyIds) .setAllowedKeyIds(allowedKeyIds)
.setDecryptMetadataOnly(decryptMetadataOnly) .setDecryptMetadataOnly(decryptMetadataOnly)
.setDetachedSignature(detachedSignature); .setDetachedSignature(detachedSignature);
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream); DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);
@@ -562,40 +564,55 @@ public class OpenPgpService extends RemoteService {
Intent result = new Intent(); Intent result = new Intent();
OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult(); OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult();
// TODO: currently RESULT_TYPE_UNENCRYPTED_UNSIGNED is never returned
// instead an error is returned when no pgp data has been found
int resultType = OpenPgpApi.RESULT_TYPE_UNENCRYPTED_UNSIGNED;
if (signatureResult != null) {
resultType |= OpenPgpApi.RESULT_TYPE_SIGNED;
if (!signatureResult.isSignatureOnly()) {
resultType |= OpenPgpApi.RESULT_TYPE_ENCRYPTED;
}
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult); result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult);
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 5) { if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_KEY_MISSING) {
// SIGNATURE_KEY_REVOKED and SIGNATURE_KEY_EXPIRED have been added in version 5 // If signature is unknown we return an _additional_ PendingIntent
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED // to retrieve the missing key
|| signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED) { result.putExtra(OpenPgpApi.RESULT_INTENT, getKeyserverPendingIntent(data, signatureResult.getKeyId()));
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
}
}
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) {
// If signature is unknown we return an _additional_ PendingIntent
// to retrieve the missing key
result.putExtra(OpenPgpApi.RESULT_INTENT, getKeyserverPendingIntent(data, signatureResult.getKeyId()));
} else {
// If signature key is known, return PendingIntent to show key
result.putExtra(OpenPgpApi.RESULT_INTENT, getShowKeyPendingIntent(signatureResult.getKeyId()));
}
} else { } else {
resultType |= OpenPgpApi.RESULT_TYPE_ENCRYPTED; // If signature key is known, return PendingIntent to show key
result.putExtra(OpenPgpApi.RESULT_INTENT, getShowKeyPendingIntent(signatureResult.getKeyId()));
} }
result.putExtra(OpenPgpApi.RESULT_TYPE, resultType);
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 5) {
// RESULT_INVALID_KEY_REVOKED and RESULT_INVALID_KEY_EXPIRED have been added in version 5
if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED
|| signatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED) {
signatureResult.setResult(OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE);
}
}
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 6) {
// RESULT_INVALID_INSECURE has been added in version 6, fallback to RESULT_INVALID_SIGNATURE
if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_INSECURE) {
signatureResult.setResult(OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE);
}
// RESULT_NO_SIGNATURE has been added in version 6, before the signatureResult was null
if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, (Parcelable[]) null);
}
OpenPgpDecryptionResult decryptionResult = pgpResult.getDecryptionResult();
if (decryptionResult.getResult() != OpenPgpDecryptionResult.RESULT_ENCRYPTED
&& signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
// not encrypted and signed, set deprecated signatureOnly variable
signatureResult.setSignatureOnly(true);
}
}
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 6) {
OpenPgpDecryptionResult decryptionResult = pgpResult.getDecryptionResult();
if (decryptionResult != null) {
result.putExtra(OpenPgpApi.RESULT_DECRYPTION, decryptionResult);
}
}
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 4) { if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 4) {
OpenPgpMetadata metadata = pgpResult.getDecryptMetadata(); OpenPgpMetadata metadata = pgpResult.getDecryptionMetadata();
if (metadata != null) { if (metadata != null) {
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata); result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
} }
@@ -647,6 +664,7 @@ public class OpenPgpService extends RemoteService {
} }
} }
} }
} }
private Intent getKeyImpl(Intent data) { private Intent getKeyImpl(Intent data) {

View File

@@ -36,6 +36,7 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ViewAnimator; import android.widget.ViewAnimator;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@@ -208,37 +209,50 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
mDecryptVerifyResult = decryptVerifyResult; mDecryptVerifyResult = decryptVerifyResult;
mSignatureResult = decryptVerifyResult.getSignatureResult(); mSignatureResult = decryptVerifyResult.getSignatureResult();
OpenPgpDecryptionResult decryptionResult = decryptVerifyResult.getDecryptionResult();
mResultLayout.setVisibility(View.VISIBLE); mResultLayout.setVisibility(View.VISIBLE);
// unsigned data switch (decryptionResult.getResult()) {
if (mSignatureResult == null) { case OpenPgpDecryptionResult.RESULT_ENCRYPTED: {
mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
break;
}
case OpenPgpDecryptionResult.RESULT_INSECURE: {
mEncryptionText.setText(R.string.decrypt_result_insecure);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.INSECURE);
break;
}
default:
case OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED: {
mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
break;
}
}
if (mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
// no signature
setSignatureLayoutVisibility(View.GONE); setSignatureLayoutVisibility(View.GONE);
mSignatureText.setText(R.string.decrypt_result_no_signature); mSignatureText.setText(R.string.decrypt_result_no_signature);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.NOT_SIGNED); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.NOT_SIGNED);
mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
getLoaderManager().destroyLoader(LOADER_ID_UNIFIED); getLoaderManager().destroyLoader(LOADER_ID_UNIFIED);
showErrorOverlay(false); showErrorOverlay(false);
onVerifyLoaded(true); onVerifyLoaded(true);
return;
}
if (mSignatureResult.isSignatureOnly()) {
mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
} else { } else {
mEncryptionText.setText(R.string.decrypt_result_encrypted); // signature present
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
}
getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); // after loader is restarted signature results are checked
getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this);
}
} }
private void setSignatureLayoutVisibility(int visibility) { private void setSignatureLayoutVisibility(int visibility) {
@@ -313,8 +327,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
// NOTE: Don't use revoked and expired fields from database, they don't show // NOTE: Don't use revoked and expired fields from database, they don't show
// revoked/expired subkeys // revoked/expired subkeys
boolean isRevoked = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED; boolean isRevoked = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED;
boolean isExpired = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED; boolean isExpired = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED;
boolean isInsecure = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_INSECURE;
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
@@ -338,6 +353,17 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
onVerifyLoaded(true); onVerifyLoaded(true);
} else if (isInsecure) {
mSignatureText.setText(R.string.decrypt_result_insecure_cryptography);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INSECURE);
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(signatureKeyId);
showErrorOverlay(false);
onVerifyLoaded(true);
} else if (isYours) { } else if (isYours) {
mSignatureText.setText(R.string.decrypt_result_signature_secret); mSignatureText.setText(R.string.decrypt_result_signature_secret);
@@ -389,9 +415,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
final long signatureKeyId = mSignatureResult.getKeyId(); final long signatureKeyId = mSignatureResult.getKeyId();
int result = mSignatureResult.getStatus(); int result = mSignatureResult.getResult();
if (result != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING if (result != OpenPgpSignatureResult.RESULT_KEY_MISSING
&& result != OpenPgpSignatureResult.SIGNATURE_ERROR) { && result != OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE) {
Log.e(Constants.TAG, "got missing status for non-missing key, shouldn't happen!"); Log.e(Constants.TAG, "got missing status for non-missing key, shouldn't happen!");
} }
@@ -409,9 +435,9 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
getActivity(), mSignatureResult.getKeyId())); getActivity(), mSignatureResult.getKeyId()));
} }
switch (mSignatureResult.getStatus()) { switch (mSignatureResult.getResult()) {
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { case OpenPgpSignatureResult.RESULT_KEY_MISSING: {
mSignatureText.setText(R.string.decrypt_result_signature_missing_key); mSignatureText.setText(R.string.decrypt_result_signature_missing_key);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY);
@@ -433,7 +459,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
break; break;
} }
case OpenPgpSignatureResult.SIGNATURE_ERROR: { case OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE: {
mSignatureText.setText(R.string.decrypt_result_invalid_signature); mSignatureText.setText(R.string.decrypt_result_invalid_signature);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID);

View File

@@ -321,11 +321,11 @@ public class DecryptListFragment
protected Drawable doInBackground(Void... params) { protected Drawable doInBackground(Void... params) {
Context context = getActivity(); Context context = getActivity();
if (result.getDecryptMetadata() == null || context == null) { if (result.getDecryptionMetadata() == null || context == null) {
return null; return null;
} }
String type = result.getDecryptMetadata().getMimeType(); String type = result.getDecryptionMetadata().getMimeType();
Uri outputUri = mOutputUris.get(uri); Uri outputUri = mOutputUris.get(uri);
if (type == null || outputUri == null) { if (type == null || outputUri == null) {
return null; return null;
@@ -368,7 +368,7 @@ public class DecryptListFragment
OpenPgpSignatureResult sigResult = result.getSignatureResult(); OpenPgpSignatureResult sigResult = result.getSignatureResult();
if (sigResult != null) { if (sigResult != null) {
final long keyId = sigResult.getKeyId(); final long keyId = sigResult.getKeyId();
if (sigResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) { if (sigResult.getResult() != OpenPgpSignatureResult.RESULT_KEY_MISSING) {
onKeyClick = new OnClickListener() { onKeyClick = new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@@ -384,7 +384,7 @@ public class DecryptListFragment
} }
} }
if (result.success() && result.getDecryptMetadata() != null) { if (result.success() && result.getDecryptionMetadata() != null) {
onFileClick = new OnClickListener() { onFileClick = new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@@ -425,7 +425,7 @@ public class DecryptListFragment
return; return;
} }
final OpenPgpMetadata metadata = result.getDecryptMetadata(); final OpenPgpMetadata metadata = result.getDecryptionMetadata();
// text/plain is a special case where we extract the uri content into // text/plain is a special case where we extract the uri content into
// the EXTRA_TEXT extra ourselves, and display a chooser which includes // the EXTRA_TEXT extra ourselves, and display a chooser which includes
@@ -529,7 +529,7 @@ public class DecryptListFragment
activity.startActivity(intent); activity.startActivity(intent);
return true; return true;
case R.id.decrypt_save: case R.id.decrypt_save:
OpenPgpMetadata metadata = result.getDecryptMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
if (metadata == null) { if (metadata == null) {
return true; return true;
} }
@@ -724,7 +724,7 @@ public class DecryptListFragment
KeyFormattingUtils.setStatus(mContext, holder, model.mResult); KeyFormattingUtils.setStatus(mContext, holder, model.mResult);
final OpenPgpMetadata metadata = model.mResult.getDecryptMetadata(); final OpenPgpMetadata metadata = model.mResult.getDecryptionMetadata();
String filename; String filename;
if (metadata == null) { if (metadata == null) {

View File

@@ -553,14 +553,18 @@ public class EncryptFilesFragment
data.addInputUris(mFilesAdapter.getAsArrayList()); data.addInputUris(mFilesAdapter.getAsArrayList());
if (mUseCompression) { if (mUseCompression) {
data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else { } else {
data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
} }
data.setHiddenRecipients(mHiddenRecipients); data.setHiddenRecipients(mHiddenRecipients);
data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor); data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor);
data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); data.setSymmetricEncryptionAlgorithm(
data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
EncryptActivity encryptActivity = (EncryptActivity) getActivity(); EncryptActivity encryptActivity = (EncryptActivity) getActivity();
EncryptModeFragment modeFragment = encryptActivity.getModeFragment(); EncryptModeFragment modeFragment = encryptActivity.getModeFragment();

View File

@@ -223,15 +223,17 @@ public class EncryptTextFragment
data.setCleartextSignature(true); data.setCleartextSignature(true);
if (mUseCompression) { if (mUseCompression) {
data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else { } else {
data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
} }
data.setHiddenRecipients(mHiddenRecipients); data.setHiddenRecipients(mHiddenRecipients);
data.setSymmetricEncryptionAlgorithm( data.setSymmetricEncryptionAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm( data.setSignatureHashAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
// Always use armor for messages // Always use armor for messages
data.setEnableAsciiArmorOutput(true); data.setEnableAsciiArmorOutput(true);

View File

@@ -28,6 +28,7 @@ import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1ObjectIdentifier;
import org.spongycastle.asn1.nist.NISTNamedCurves; import org.spongycastle.asn1.nist.NISTNamedCurves;
@@ -40,7 +41,6 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -408,7 +408,8 @@ public class KeyFormattingUtils {
UNVERIFIED, UNVERIFIED,
UNKNOWN_KEY, UNKNOWN_KEY,
INVALID, INVALID,
NOT_SIGNED NOT_SIGNED,
INSECURE
} }
public static void setStatusImage(Context context, ImageView statusIcon, State state) { public static void setStatusImage(Context context, ImageView statusIcon, State state) {
@@ -443,18 +444,33 @@ public class KeyFormattingUtils {
@SuppressWarnings("deprecation") // context.getDrawable is api lvl 21, need to use deprecated @SuppressWarnings("deprecation") // context.getDrawable is api lvl 21, need to use deprecated
public static void setStatus(Context context, StatusHolder holder, DecryptVerifyResult result) { public static void setStatus(Context context, StatusHolder holder, DecryptVerifyResult result) {
OpenPgpSignatureResult signatureResult = result.getSignatureResult();
if (holder.hasEncrypt()) { if (holder.hasEncrypt()) {
OpenPgpDecryptionResult decryptionResult = result.getDecryptionResult();
int encText, encIcon, encColor; int encText, encIcon, encColor;
if (signatureResult != null && signatureResult.isSignatureOnly()) {
encIcon = R.drawable.status_lock_open_24dp; switch (decryptionResult.getResult()) {
encText = R.string.decrypt_result_not_encrypted; case OpenPgpDecryptionResult.RESULT_ENCRYPTED: {
encColor = R.color.key_flag_red; encText = R.string.decrypt_result_encrypted;
} else { encIcon = R.drawable.status_lock_closed_24dp;
encIcon = R.drawable.status_lock_closed_24dp; encColor = R.color.key_flag_green;
encText = R.string.decrypt_result_encrypted; break;
encColor = R.color.key_flag_green; }
case OpenPgpDecryptionResult.RESULT_INSECURE: {
encText = R.string.decrypt_result_insecure;
encIcon = R.drawable.status_signature_invalid_cutout_24dp;
encColor = R.color.key_flag_red;
break;
}
default:
case OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED: {
encText = R.string.decrypt_result_not_encrypted;
encIcon = R.drawable.status_lock_open_24dp;
encColor = R.color.key_flag_red;
break;
}
} }
int encColorRes = context.getResources().getColor(encColor); int encColorRes = context.getResources().getColor(encColor);
@@ -464,22 +480,27 @@ public class KeyFormattingUtils {
holder.getEncryptionStatusText().setTextColor(encColorRes); holder.getEncryptionStatusText().setTextColor(encColorRes);
} }
OpenPgpSignatureResult signatureResult = result.getSignatureResult();
int sigText, sigIcon, sigColor; int sigText, sigIcon, sigColor;
int sigActionText, sigActionIcon; int sigActionText, sigActionIcon;
if (signatureResult == null) { switch (signatureResult.getResult()) {
sigText = R.string.decrypt_result_no_signature; case OpenPgpSignatureResult.RESULT_NO_SIGNATURE: {
sigIcon = R.drawable.status_signature_invalid_cutout_24dp; // no signature
sigColor = R.color.key_flag_gray;
// won't be used, but makes compiler happy sigText = R.string.decrypt_result_no_signature;
sigActionText = 0; sigIcon = R.drawable.status_signature_invalid_cutout_24dp;
sigActionIcon = 0; sigColor = R.color.key_flag_gray;
} else switch (signatureResult.getStatus()) { // won't be used, but makes compiler happy
sigActionText = 0;
sigActionIcon = 0;
break;
}
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { case OpenPgpSignatureResult.RESULT_VALID_CONFIRMED: {
sigText = R.string.decrypt_result_signature_certified; sigText = R.string.decrypt_result_signature_certified;
sigIcon = R.drawable.status_signature_verified_cutout_24dp; sigIcon = R.drawable.status_signature_verified_cutout_24dp;
sigColor = R.color.key_flag_green; sigColor = R.color.key_flag_green;
@@ -489,7 +510,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { case OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED: {
sigText = R.string.decrypt_result_signature_uncertified; sigText = R.string.decrypt_result_signature_uncertified;
sigIcon = R.drawable.status_signature_unverified_cutout_24dp; sigIcon = R.drawable.status_signature_unverified_cutout_24dp;
sigColor = R.color.key_flag_orange; sigColor = R.color.key_flag_orange;
@@ -499,7 +520,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { case OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED: {
sigText = R.string.decrypt_result_signature_revoked_key; sigText = R.string.decrypt_result_signature_revoked_key;
sigIcon = R.drawable.status_signature_revoked_cutout_24dp; sigIcon = R.drawable.status_signature_revoked_cutout_24dp;
sigColor = R.color.key_flag_red; sigColor = R.color.key_flag_red;
@@ -509,7 +530,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { case OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED: {
sigText = R.string.decrypt_result_signature_expired_key; sigText = R.string.decrypt_result_signature_expired_key;
sigIcon = R.drawable.status_signature_expired_cutout_24dp; sigIcon = R.drawable.status_signature_expired_cutout_24dp;
sigColor = R.color.key_flag_red; sigColor = R.color.key_flag_red;
@@ -519,7 +540,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { case OpenPgpSignatureResult.RESULT_KEY_MISSING: {
sigText = R.string.decrypt_result_signature_missing_key; sigText = R.string.decrypt_result_signature_missing_key;
sigIcon = R.drawable.status_signature_unknown_cutout_24dp; sigIcon = R.drawable.status_signature_unknown_cutout_24dp;
sigColor = R.color.key_flag_red; sigColor = R.color.key_flag_red;
@@ -529,8 +550,18 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.RESULT_INVALID_INSECURE: {
sigText = R.string.decrypt_result_insecure_cryptography;
sigIcon = R.drawable.status_signature_invalid_cutout_24dp;
sigColor = R.color.key_flag_red;
sigActionText = R.string.decrypt_result_action_show;
sigActionIcon = R.drawable.ic_vpn_key_grey_24dp;
break;
}
default: default:
case OpenPgpSignatureResult.SIGNATURE_ERROR: { case OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE: {
sigText = R.string.decrypt_result_invalid_signature; sigText = R.string.decrypt_result_invalid_signature;
sigIcon = R.drawable.status_signature_invalid_cutout_24dp; sigIcon = R.drawable.status_signature_invalid_cutout_24dp;
sigColor = R.color.key_flag_red; sigColor = R.color.key_flag_red;
@@ -548,7 +579,8 @@ public class KeyFormattingUtils {
holder.getSignatureStatusText().setText(sigText); holder.getSignatureStatusText().setText(sigText);
holder.getSignatureStatusText().setTextColor(sigColorRes); holder.getSignatureStatusText().setTextColor(sigColorRes);
if (signatureResult != null) { if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
// has a signature, thus display layouts
holder.getSignatureLayout().setVisibility(View.VISIBLE); holder.getSignatureLayout().setVisibility(View.VISIBLE);
@@ -556,7 +588,7 @@ public class KeyFormattingUtils {
holder.getSignatureAction().setCompoundDrawablesWithIntrinsicBounds( holder.getSignatureAction().setCompoundDrawablesWithIntrinsicBounds(
0, 0, sigActionIcon, 0); 0, 0, sigActionIcon, 0);
String userId = signatureResult.getPrimaryUserId(); String userId = result.getSignatureResult().getPrimaryUserId();
KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
if (userIdSplit.name != null) { if (userIdSplit.name != null) {
holder.getSignatureUserName().setText(userIdSplit.name); holder.getSignatureUserName().setText(userIdSplit.name);
@@ -687,6 +719,24 @@ public class KeyFormattingUtils {
} }
break; break;
} }
case INSECURE: {
if (big) {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_96dp));
} else {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.key_flag_red;
}
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case NOT_ENCRYPTED: { case NOT_ENCRYPTED: {
statusIcon.setImageDrawable( statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_lock_open_24dp)); context.getResources().getDrawable(R.drawable.status_lock_open_24dp));

View File

@@ -343,6 +343,7 @@
<!-- results shown after decryption/verification --> <!-- results shown after decryption/verification -->
<string name="decrypt_result_no_signature">"Not Signed"</string> <string name="decrypt_result_no_signature">"Not Signed"</string>
<string name="decrypt_result_invalid_signature">"Invalid signature!"</string> <string name="decrypt_result_invalid_signature">"Invalid signature!"</string>
<string name="decrypt_result_insecure_cryptography">"Invalid signature (Insecure Cryptography)!"</string>
<string name="decrypt_result_signature_uncertified">"Signed by <b>unconfirmed</b> key"</string> <string name="decrypt_result_signature_uncertified">"Signed by <b>unconfirmed</b> key"</string>
<string name="decrypt_result_signature_secret">"Signed by your key"</string> <string name="decrypt_result_signature_secret">"Signed by your key"</string>
<string name="decrypt_result_signature_certified">"Signed by confirmed key"</string> <string name="decrypt_result_signature_certified">"Signed by confirmed key"</string>
@@ -351,6 +352,7 @@
<string name="decrypt_result_signature_missing_key">"Signed by <b>unknown public key</b>"</string> <string name="decrypt_result_signature_missing_key">"Signed by <b>unknown public key</b>"</string>
<string name="decrypt_result_encrypted">"Encrypted"</string> <string name="decrypt_result_encrypted">"Encrypted"</string>
<string name="decrypt_result_not_encrypted">"Not Encrypted"</string> <string name="decrypt_result_not_encrypted">"Not Encrypted"</string>
<string name="decrypt_result_insecure">"Insecure Encryption"</string>
<string name="decrypt_result_action_show">"Show"</string> <string name="decrypt_result_action_show">"Show"</string>
<string name="decrypt_result_action_Lookup">"Lookup"</string> <string name="decrypt_result_action_Lookup">"Lookup"</string>
<string name="decrypt_invalid_text">"Either the signature is invalid or the key has been revoked. You cannot be sure who wrote the text. Do you still want to display it?"</string> <string name="decrypt_invalid_text">"Either the signature is invalid or the key has been revoked. You cannot be sure who wrote the text. Do you still want to display it?"</string>
@@ -1163,7 +1165,7 @@
<string name="msg_dc_trail_sym">"Encountered trailing, symmetrically encrypted data"</string> <string name="msg_dc_trail_sym">"Encountered trailing, symmetrically encrypted data"</string>
<string name="msg_dc_trail_unknown">"Encountered trailing data of unknown type"</string> <string name="msg_dc_trail_unknown">"Encountered trailing data of unknown type"</string>
<string name="msg_dc_unlocking">"Unlocking secret key"</string> <string name="msg_dc_unlocking">"Unlocking secret key"</string>
<string name="msg_dc_old_symmetric_encryption_algo">"Potentially insecure encryption algorithm has been used!"</string> <string name="msg_dc_old_symmetric_encryption_algo">"Insecure encryption algorithm has been used!"</string>
<!-- Messages for VerifySignedLiteralData operation --> <!-- Messages for VerifySignedLiteralData operation -->
<string name="msg_vl">"Starting signature check"</string> <string name="msg_vl">"Starting signature check"</string>

View File

@@ -191,7 +191,7 @@ public class PgpEncryptDecryptTest {
Assert.assertEquals("cached session keys must be empty", Assert.assertEquals("cached session keys must be empty",
0, cryptoInput.getCryptoData().size()); 0, cryptoInput.getCryptoData().size());
OpenPgpMetadata metadata = result.getDecryptMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
out.toByteArray().length, metadata.getOriginalSize()); out.toByteArray().length, metadata.getOriginalSize());
} }
@@ -297,7 +297,7 @@ public class PgpEncryptDecryptTest {
Assert.assertEquals("must have one cached session key", Assert.assertEquals("must have one cached session key",
1, cryptoInput.getCryptoData().size()); 1, cryptoInput.getCryptoData().size());
OpenPgpMetadata metadata = result.getDecryptMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
out.toByteArray().length, metadata.getOriginalSize()); out.toByteArray().length, metadata.getOriginalSize());
@@ -486,7 +486,7 @@ public class PgpEncryptDecryptTest {
out.toByteArray(), plaintext.getBytes()); out.toByteArray(), plaintext.getBytes());
Assert.assertNull("signature should be empty", result.getSignatureResult()); Assert.assertNull("signature should be empty", result.getSignatureResult());
OpenPgpMetadata metadata = result.getDecryptMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
out.toByteArray().length, metadata.getOriginalSize()); out.toByteArray().length, metadata.getOriginalSize());
} }
@@ -604,9 +604,9 @@ public class PgpEncryptDecryptTest {
Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext", Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
out.toByteArray(), plaintext.getBytes()); out.toByteArray(), plaintext.getBytes());
Assert.assertEquals("signature should be verified and certified", Assert.assertEquals("signature should be verified and certified",
OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED, result.getSignatureResult().getStatus()); OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult());
OpenPgpMetadata metadata = result.getDecryptMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
out.toByteArray().length, metadata.getOriginalSize()); out.toByteArray().length, metadata.getOriginalSize());
} }
@@ -631,8 +631,8 @@ public class PgpEncryptDecryptTest {
Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext", Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
out.toByteArray(), plaintext.getBytes()); out.toByteArray(), plaintext.getBytes());
Assert.assertEquals("signature key should be missing", Assert.assertEquals("signature key should be missing",
OpenPgpSignatureResult.SIGNATURE_KEY_MISSING, OpenPgpSignatureResult.RESULT_KEY_MISSING,
result.getSignatureResult().getStatus()); result.getSignatureResult().getResult());
} }
} }