Introduce constants in OpenPgpSignature and DecryptionResult for unsigned/unencrypted content, update API, introduce simple checks for insecure symmetric algos
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -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
|
||||||
|
|||||||
@@ -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>() {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
2
extern/openpgp-api-lib
vendored
2
extern/openpgp-api-lib
vendored
Submodule extern/openpgp-api-lib updated: 5a24bb3428...b42636ec3e
Reference in New Issue
Block a user