Introduce constants in OpenPgpSignature and DecryptionResult for unsigned/unencrypted content, update API, introduce simple checks for insecure symmetric algos
This commit is contained in:
@@ -184,7 +184,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
// TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS
|
||||
// choose best algo
|
||||
|
||||
return PgpConstants.sPreferredHashAlgorithms;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo,
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class OpenPgpSignatureResultBuilder {
|
||||
// OpenPgpSignatureResult
|
||||
private boolean mSignatureOnly = false;
|
||||
private String mPrimaryUserId;
|
||||
private ArrayList<String> mUserIds = new ArrayList<>();
|
||||
private long mKeyId;
|
||||
@@ -42,10 +41,7 @@ public class OpenPgpSignatureResultBuilder {
|
||||
private boolean mIsSignatureKeyCertified = false;
|
||||
private boolean mIsKeyRevoked = false;
|
||||
private boolean mIsKeyExpired = false;
|
||||
|
||||
public void setSignatureOnly(boolean signatureOnly) {
|
||||
this.mSignatureOnly = signatureOnly;
|
||||
}
|
||||
private boolean mInsecure = false;
|
||||
|
||||
public void setPrimaryUserId(String userId) {
|
||||
this.mPrimaryUserId = userId;
|
||||
@@ -63,6 +59,10 @@ public class OpenPgpSignatureResultBuilder {
|
||||
this.mValidSignature = validSignature;
|
||||
}
|
||||
|
||||
public void setInsecure(boolean insecure) {
|
||||
this.mInsecure = insecure;
|
||||
}
|
||||
|
||||
public void setSignatureKeyCertified(boolean isSignatureKeyCertified) {
|
||||
this.mIsSignatureKeyCertified = isSignatureKeyCertified;
|
||||
}
|
||||
@@ -87,6 +87,10 @@ public class OpenPgpSignatureResultBuilder {
|
||||
return mValidSignature;
|
||||
}
|
||||
|
||||
public boolean isInsecure() {
|
||||
return mInsecure;
|
||||
}
|
||||
|
||||
public void initValid(CanonicalizedPublicKeyRing signingRing,
|
||||
CanonicalizedPublicKey signingKey) {
|
||||
setSignatureAvailable(true);
|
||||
@@ -109,47 +113,50 @@ public class OpenPgpSignatureResultBuilder {
|
||||
}
|
||||
|
||||
public OpenPgpSignatureResult build() {
|
||||
if (mSignatureAvailable) {
|
||||
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);
|
||||
}
|
||||
OpenPgpSignatureResult result = new OpenPgpSignatureResult();
|
||||
|
||||
if (!mSignatureAvailable) {
|
||||
Log.d(Constants.TAG, "RESULT_NO_SIGNATURE");
|
||||
result.setResult(OpenPgpSignatureResult.RESULT_NO_SIGNATURE);
|
||||
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.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 static ArrayList<Integer> sPreferredSymmetricAlgorithms = new ArrayList<>();
|
||||
public static ArrayList<Integer> sPreferredHashAlgorithms = new ArrayList<>();
|
||||
public static ArrayList<Integer> sPreferredCompressionAlgorithms = new ArrayList<>();
|
||||
// public interface MIN_REQUIREMENT {
|
||||
// int MIN_BITS;
|
||||
// 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
|
||||
* These arrays are written as preferred algorithms into the keys on creation.
|
||||
* 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 {
|
||||
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_256);
|
||||
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_192);
|
||||
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_128);
|
||||
sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.TWOFISH);
|
||||
public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
|
||||
SymmetricKeyAlgorithmTags.AES_256,
|
||||
SymmetricKeyAlgorithmTags.AES_192,
|
||||
SymmetricKeyAlgorithmTags.AES_128,
|
||||
SymmetricKeyAlgorithmTags.TWOFISH
|
||||
};
|
||||
|
||||
// NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?)
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA256);
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA512);
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA384);
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA224);
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA1);
|
||||
sPreferredHashAlgorithms.add(HashAlgorithmTags.RIPEMD160);
|
||||
// NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?)
|
||||
public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
|
||||
HashAlgorithmTags.SHA256,
|
||||
HashAlgorithmTags.SHA512,
|
||||
HashAlgorithmTags.SHA384,
|
||||
HashAlgorithmTags.SHA224,
|
||||
};
|
||||
|
||||
/*
|
||||
* Prefer ZIP
|
||||
* "ZLIB provides no benefit over ZIP and is more malleable"
|
||||
* - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives")
|
||||
* BZIP2: very slow
|
||||
*/
|
||||
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZIP);
|
||||
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZLIB);
|
||||
sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.BZIP2);
|
||||
}
|
||||
/*
|
||||
* Prefer ZIP
|
||||
* "ZLIB provides no benefit over ZIP and is more malleable"
|
||||
* - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives")
|
||||
* BZIP2: very slow
|
||||
*/
|
||||
public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
|
||||
CompressionAlgorithmTags.ZIP,
|
||||
CompressionAlgorithmTags.ZLIB,
|
||||
CompressionAlgorithmTags.BZIP2
|
||||
};
|
||||
|
||||
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
|
||||
* 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_HASH_ALGO = HashAlgorithmTags.SHA256;
|
||||
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,
|
||||
// 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 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.webkit.MimeTypeMap;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
import org.openintents.openpgp.OpenPgpMetadata;
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
import org.spongycastle.bcpg.ArmoredInputStream;
|
||||
@@ -283,10 +284,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
|
||||
PGPSignature messageSignature = signatureList.get(signatureIndex);
|
||||
|
||||
// these are not cleartext signatures!
|
||||
// TODO: what about binary signatures?
|
||||
signatureResultBuilder.setSignatureOnly(false);
|
||||
|
||||
// Verify signature and check binding signatures
|
||||
boolean validSignature = signature.verify(messageSignature);
|
||||
if (validSignature) {
|
||||
@@ -298,8 +295,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
|
||||
OpenPgpSignatureResult signatureResult = signatureResultBuilder.build();
|
||||
|
||||
if (signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED
|
||||
&& signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED) {
|
||||
if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_CONFIRMED
|
||||
&& signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED) {
|
||||
log.add(LogType.MSG_VL_ERROR_INTEGRITY_CHECK, indent);
|
||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
@@ -309,9 +306,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
log.add(LogType.MSG_VL_OK, indent);
|
||||
|
||||
// Return a positive result, with metadata and verification info
|
||||
DecryptVerifyResult result =
|
||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
result.setSignatureResult(signatureResult);
|
||||
result.setDecryptionResult(
|
||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -322,6 +320,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
|
||||
InputStream in, OutputStream out, int indent) throws IOException, PGPException {
|
||||
|
||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||
OpenPgpDecryptionResult decryptionResult = new OpenPgpDecryptionResult();
|
||||
OperationLog log = new OperationLog();
|
||||
|
||||
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);
|
||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_ENCRYPTED);
|
||||
|
||||
// Warn about old encryption algorithms!
|
||||
if (!PgpConstants.sPreferredSymmetricAlgorithms.contains(symmetricEncryptionAlgo)) {
|
||||
// Check for insecure encryption algorithms!
|
||||
if (!PgpConstants.sSymmetricAlgorithmsWhitelist.contains(symmetricEncryptionAlgo)) {
|
||||
log.add(LogType.MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
|
||||
decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE);
|
||||
}
|
||||
|
||||
JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
|
||||
Object dataChunk = plainFact.nextObject();
|
||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||
int signatureIndex = -1;
|
||||
CanonicalizedPublicKeyRing signingRing = null;
|
||||
CanonicalizedPublicKey signingKey = null;
|
||||
@@ -752,7 +753,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
DecryptVerifyResult result =
|
||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
result.setCharset(charset);
|
||||
result.setDecryptMetadata(metadata);
|
||||
result.setDecryptionMetadata(metadata);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -809,11 +810,9 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
|
||||
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
|
||||
boolean validSignature = signature.verify(messageSignature);
|
||||
if (validSignature) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Don't allow verification of old hash algorithms!
|
||||
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) {
|
||||
validSignature = false;
|
||||
// check for insecure hash algorithms
|
||||
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
|
||||
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
|
||||
signatureResultBuilder.setInsecure(true);
|
||||
}
|
||||
|
||||
signatureResultBuilder.setValidSignature(validSignature);
|
||||
@@ -852,7 +851,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
Log.d(Constants.TAG, "MDC fail");
|
||||
if (!signatureResultBuilder.isValidSignature()) {
|
||||
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);
|
||||
|
||||
// Return a positive result, with metadata and verification info
|
||||
DecryptVerifyResult result =
|
||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
result.setCachedCryptoInputParcel(cryptoInput);
|
||||
result.setDecryptMetadata(metadata);
|
||||
result.setSignatureResult(signatureResultBuilder.build());
|
||||
result.setCharset(charset);
|
||||
result.setDecryptionResult(decryptionResult);
|
||||
result.setDecryptionMetadata(metadata);
|
||||
return result;
|
||||
|
||||
}
|
||||
@@ -885,8 +884,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
OperationLog log = new OperationLog();
|
||||
|
||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||
// cleartext signatures are never encrypted ;)
|
||||
signatureResultBuilder.setSignatureOnly(true);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
@@ -956,10 +953,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
||||
}
|
||||
|
||||
// Don't allow verification of old hash algorithms!
|
||||
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) {
|
||||
validSignature = false;
|
||||
// check for insecure hash algorithms
|
||||
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
|
||||
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
|
||||
signatureResultBuilder.setInsecure(true);
|
||||
}
|
||||
|
||||
signatureResultBuilder.setValidSignature(validSignature);
|
||||
@@ -981,8 +978,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
clearText.length);
|
||||
|
||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
result.setDecryptMetadata(metadata);
|
||||
result.setSignatureResult(signatureResultBuilder.build());
|
||||
result.setDecryptionResult(
|
||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
||||
result.setDecryptionMetadata(metadata);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -994,8 +993,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
OperationLog log = new OperationLog();
|
||||
|
||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||
// detached signatures are never encrypted
|
||||
signatureResultBuilder.setSignatureOnly(true);
|
||||
|
||||
updateProgress(R.string.progress_processing_signature, 0, 100);
|
||||
InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature());
|
||||
@@ -1050,9 +1047,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
||||
|
||||
// these are not cleartext signatures!
|
||||
signatureResultBuilder.setSignatureOnly(false);
|
||||
|
||||
// Verify signature and check binding signatures
|
||||
boolean validSignature = signature.verify();
|
||||
if (validSignature) {
|
||||
@@ -1061,10 +1055,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
||||
}
|
||||
|
||||
// Don't allow verification of old hash algorithms!
|
||||
if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) {
|
||||
validSignature = false;
|
||||
// check for insecure hash algorithms
|
||||
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
|
||||
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
|
||||
signatureResultBuilder.setInsecure(true);
|
||||
}
|
||||
|
||||
signatureResultBuilder.setValidSignature(validSignature);
|
||||
@@ -1076,6 +1070,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
|
||||
|
||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||
result.setSignatureResult(signatureResultBuilder.build());
|
||||
result.setDecryptionResult(
|
||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1206,7 +1206,7 @@ public class PgpKeyOperation {
|
||||
// add packet with EMPTY notation data (updates old one, but will be stripped later)
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@@ -1233,7 +1233,7 @@ public class PgpKeyOperation {
|
||||
// add packet with "pin" notation data
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@@ -1440,13 +1440,13 @@ public class PgpKeyOperation {
|
||||
if (divertToCard) {
|
||||
// use synchronous "NFC based" SignerBuilder
|
||||
builder = new NfcSyncPGPContentSignerBuilder(
|
||||
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO,
|
||||
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO,
|
||||
pKey.getKeyID(), cryptoInput.getCryptoData())
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
} else {
|
||||
// content signer based on signing key algorithm and chosen hash algorithm
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1472,11 +1472,11 @@ public class PgpKeyOperation {
|
||||
*/
|
||||
/* non-critical subpackets: */
|
||||
hashedPacketsGen.setPreferredSymmetricAlgorithms(false,
|
||||
PgpConstants.getAsArray(PgpConstants.sPreferredSymmetricAlgorithms));
|
||||
PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredHashAlgorithms(false,
|
||||
PgpConstants.getAsArray(PgpConstants.sPreferredHashAlgorithms));
|
||||
PgpConstants.PREFERRED_HASH_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredCompressionAlgorithms(false,
|
||||
PgpConstants.getAsArray(PgpConstants.sPreferredCompressionAlgorithms));
|
||||
PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS);
|
||||
hashedPacketsGen.setPrimaryUserID(false, primary);
|
||||
|
||||
/* 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 boolean mEnableAsciiArmorOutput = false;
|
||||
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
|
||||
protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
|
||||
protected long[] mEncryptionMasterKeyIds = 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 mSignatureSubKeyId = null;
|
||||
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
|
||||
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
|
||||
protected long mAdditionalEncryptId = Constants.key.none;
|
||||
protected boolean mFailOnMissingEncryptionKeyIds = false;
|
||||
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
|
||||
mVersionHeader = source.readString();
|
||||
mEnableAsciiArmorOutput = source.readInt() == 1;
|
||||
mCompressionId = source.readInt();
|
||||
mCompressionAlgorithm = source.readInt();
|
||||
mEncryptionMasterKeyIds = source.createLongArray();
|
||||
mSymmetricPassphrase = source.readParcelable(loader);
|
||||
mSymmetricEncryptionAlgorithm = source.readInt();
|
||||
@@ -79,7 +79,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mVersionHeader);
|
||||
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
|
||||
dest.writeInt(mCompressionId);
|
||||
dest.writeInt(mCompressionAlgorithm);
|
||||
dest.writeLongArray(mEncryptionMasterKeyIds);
|
||||
dest.writeParcelable(mSymmetricPassphrase, 0);
|
||||
dest.writeInt(mSymmetricEncryptionAlgorithm);
|
||||
@@ -174,12 +174,12 @@ public class PgpSignEncryptInputParcel implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getCompressionId() {
|
||||
return mCompressionId;
|
||||
public int getCompressionAlgorithm() {
|
||||
return mCompressionAlgorithm;
|
||||
}
|
||||
|
||||
public PgpSignEncryptInputParcel setCompressionId(int compressionId) {
|
||||
mCompressionId = compressionId;
|
||||
public PgpSignEncryptInputParcel setCompressionAlgorithm(int compressionAlgorithm) {
|
||||
mCompressionAlgorithm = compressionAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none;
|
||||
boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0)
|
||||
|| input.getSymmetricPassphrase() != null);
|
||||
boolean enableCompression = (input.getCompressionId() != CompressionAlgorithmTags.UNCOMPRESSED);
|
||||
boolean enableCompression = (input.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED);
|
||||
|
||||
Log.d(Constants.TAG, "enableSignature:" + enableSignature
|
||||
+ "\nenableEncryption:" + enableEncryption
|
||||
@@ -229,9 +229,11 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
// Use preferred hash algo
|
||||
int requestedAlgorithm = input.getSignatureHashAlgorithm();
|
||||
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
|
||||
input.setSignatureHashAlgorithm(supported.get(0));
|
||||
// input.setSignatureHashAlgorithm(supported.get(0));
|
||||
} else if (!supported.contains(requestedAlgorithm)) {
|
||||
log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
@@ -245,10 +247,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
|
||||
// Use preferred encryption algo
|
||||
int algo = input.getSymmetricEncryptionAlgorithm();
|
||||
if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) {
|
||||
if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
|
||||
// get most preferred
|
||||
// TODO: get from recipients
|
||||
algo = PgpConstants.sPreferredSymmetricAlgorithms.get(0);
|
||||
algo = PgpConstants.DEFAULT_SYMMETRIC_ALGORITHM;
|
||||
}
|
||||
// has Integrity packet enabled!
|
||||
JcePGPDataEncryptorBuilder encryptorBuilder =
|
||||
@@ -341,7 +343,13 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
|
||||
if (enableCompression) {
|
||||
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));
|
||||
} else {
|
||||
bcpgOut = new BCPGOutputStream(encryptionOut);
|
||||
@@ -464,7 +472,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
InputStream in = inputData.getInputStream();
|
||||
|
||||
if (enableCompression) {
|
||||
compressGen = new PGPCompressedDataGenerator(input.getCompressionId());
|
||||
compressGen = new PGPCompressedDataGenerator(input.getCompressionAlgorithm());
|
||||
bcpgOut = new BCPGOutputStream(compressGen.open(out));
|
||||
} else {
|
||||
bcpgOut = new BCPGOutputStream(out);
|
||||
|
||||
Reference in New Issue
Block a user