Improve comments and reasons in PgpConstants, simple checks for insecure asymmetric keys

This commit is contained in:
Dominik Schürmann
2015-08-02 23:34:00 +02:00
parent 7c40d89eea
commit 3d8eda6e3e
24 changed files with 471 additions and 277 deletions

View File

@@ -611,14 +611,12 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_ERROR_CORRUPT_DATA (LogLevel.ERROR, R.string.msg_dc_error_corrupt_data),
MSG_DC_ERROR_EXTRACT_KEY (LogLevel.ERROR, R.string.msg_dc_error_extract_key),
MSG_DC_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_dc_error_integrity_check),
MSG_DC_ERROR_INTEGRITY_MISSING (LogLevel.ERROR, R.string.msg_dc_error_integrity_missing),
MSG_DC_ERROR_INVALID_DATA (LogLevel.ERROR, R.string.msg_dc_error_invalid_data),
MSG_DC_ERROR_IO (LogLevel.ERROR, R.string.msg_dc_error_io),
MSG_DC_ERROR_INPUT (LogLevel.ERROR, R.string.msg_dc_error_input),
MSG_DC_ERROR_NO_DATA (LogLevel.ERROR, R.string.msg_dc_error_no_data),
MSG_DC_ERROR_NO_KEY (LogLevel.ERROR, R.string.msg_dc_error_no_key),
MSG_DC_ERROR_PGP_EXCEPTION (LogLevel.ERROR, R.string.msg_dc_error_pgp_exception),
MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO (LogLevel.ERROR, R.string.msg_dc_error_unsupported_hash_algo),
MSG_DC_INTEGRITY_CHECK_OK (LogLevel.INFO, R.string.msg_dc_integrity_check_ok),
MSG_DC_OK_META_ONLY (LogLevel.OK, R.string.msg_dc_ok_meta_only),
MSG_DC_OK (LogLevel.OK, R.string.msg_dc_ok),
@@ -633,7 +631,10 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_TRAIL_SYM (LogLevel.DEBUG, R.string.msg_dc_trail_sym),
MSG_DC_TRAIL_UNKNOWN (LogLevel.DEBUG, R.string.msg_dc_trail_unknown),
MSG_DC_UNLOCKING (LogLevel.INFO, R.string.msg_dc_unlocking),
MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO (LogLevel.WARN, R.string.msg_dc_old_symmetric_encryption_algo),
MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO(LogLevel.WARN, R.string.msg_dc_insecure_symmetric_encryption_algo),
MSG_DC_INSECURE_HASH_ALGO(LogLevel.ERROR, R.string.msg_dc_insecure_hash_algo),
MSG_DC_INSECURE_MDC_MISSING(LogLevel.ERROR, R.string.msg_dc_insecure_mdc_missing),
MSG_DC_INSECURE_KEY(LogLevel.ERROR, R.string.msg_dc_insecure_key),
// verify signed literal data
MSG_VL (LogLevel.INFO, R.string.msg_vl),

View File

@@ -43,7 +43,6 @@ import org.sufficientlysecure.keychain.util.Passphrase;
import java.nio.ByteBuffer;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -195,7 +194,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
public PGPSignatureGenerator getCertSignatureGenerator(Map<ByteBuffer, byte[]> signedHashes) {
PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
PgpSecurityConstants.CERTIFY_HASH_ALGO, signedHashes);
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
throw new PrivateKeyNotUnlockedException();

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log;
public class OpenPgpDecryptionResultBuilder {
// builder
private boolean mInsecure = false;
private boolean mEncrypted = false;
public void setInsecure(boolean insecure) {
this.mInsecure = insecure;
}
public void setEncrypted(boolean encrypted) {
this.mEncrypted = encrypted;
}
public OpenPgpDecryptionResult build() {
OpenPgpDecryptionResult result = new OpenPgpDecryptionResult();
if (mInsecure) {
Log.d(Constants.TAG, "RESULT_INSECURE");
result.setResult(OpenPgpDecryptionResult.RESULT_INSECURE);
return result;
}
if (mEncrypted) {
Log.d(Constants.TAG, "RESULT_ENCRYPTED");
result.setResult(OpenPgpDecryptionResult.RESULT_ENCRYPTED);
} else {
Log.d(Constants.TAG, "RESULT_NOT_ENCRYPTED");
result.setResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED);
}
return result;
}
}

View File

@@ -1,174 +0,0 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
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
*
* Many decisions are based on https://gist.github.com/coruus/68a8c65571e2b4225a69
*/
public class PgpConstants {
// 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
/*
PgpDecryptVerify: Secure Algorithms Whitelist
all other algorithms will be rejected with OpenPgpDecryptionResult.RESULT_INSECURE
No broken ciphers or ciphers with key length smaller than 128 bit are allowed!
*/
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); // 128 bit
}
// all other algorithms will be rejected with OpenPgpSignatureResult.RESULT_INVALID_INSECURE
public static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>();
static {
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA512);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA384);
/*
TODO: SHA256 and SHA224 are still allowed even though
coruus advises against it, to enable better backward compatibility
coruus:
Implementations MUST NOT sign SHA-224 hashes. They SHOULD NOT accept signatures over SHA-224 hashes.
((collision resistance of 112-bits))
Implementations SHOULD NOT sign SHA-256 hashes. They MUST NOT default to signing SHA-256 hashes.
*/
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA256);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA224);
}
/*
* Most preferred is first
* These arrays are written as preferred algorithms into the keys on creation.
* Other implementations may choose to honor this selection.
*/
public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
SymmetricKeyAlgorithmTags.AES_256,
SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128,
};
/*
coorus:
Implementations SHOULD use SHA-512 for RSA or DSA signatures. They SHOULD NOT use SHA-384.
((cite to affine padding attacks; unproven status of RSA-PKCSv15))
*/
public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
HashAlgorithmTags.SHA512,
};
/*
* 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,
};
public static final int CERTIFY_HASH_ALGO = HashAlgorithmTags.SHA512;
/*
Always use AES-256! Ignore the preferred encryption algos of the recipient!
coorus:
Implementations SHOULD ignore the symmetric algorithm preferences of a recipient's public key;
in particular, implementations MUST NOT choose an algorithm forbidden by this
document because a recipient prefers it.
NEEDCITE downgrade attacks on TLS, other protocols
*/
public static final int DEFAULT_SYMMETRIC_ALGORITHM = SymmetricKeyAlgorithmTags.AES_256;
public interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags {
int USE_DEFAULT = -1;
}
/*
Always use SHA-512! Ignore the preferred hash algos of the recipient!
coorus:
Implementations MUST ignore the hash algorithm preferences of a recipient when signing
a message to a recipient. The difficulty of forging a signature under a given key,
using generic attacks on hash functions, is the difficulty of the weakest hash signed by that key.
Implementations MUST default to using SHA-512 for RSA signatures,
and either SHA-512 or the matched instance of SHA-2 for ECDSA signatures.
TODO: Ed25519
CITE: zooko's hash function table CITE: distinguishers on SHA-256
*/
public static final int DEFAULT_HASH_ALGORITHM = HashAlgorithmTags.SHA512;
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
* iterations are useful against offline attacks, as it takes more
* time to check each password. The actual number of iterations is
* rather complex, and also depends on the hash function in use.
* Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give
* you more iterations. As a rough rule of thumb, when using
* SHA256 as the hashing function, 0x10 gives you about 64
* iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0,
* or about 1 million iterations. The maximum you can go to is
* 0xff, or about 2 million iterations.
* from http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html
*
* Bouncy Castle default: 0x60
* kbsriram proposes: 0xc0
* OpenKeychain: 0x90
*/
public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90;
public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA512;
public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256;
public static final int SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA512;
// 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;
}

View File

@@ -321,7 +321,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
InputStream in, OutputStream out, int indent) throws IOException, PGPException {
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
OpenPgpDecryptionResult decryptionResult = new OpenPgpDecryptionResult();
OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
OperationLog log = new OperationLog();
log.add(LogType.MSG_DC, indent);
@@ -464,6 +464,12 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
}
// check for insecure encryption key
if ( ! PgpSecurityConstants.isSecureKey(secretEncryptionKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
decryptionResultBuilder.setInsecure(true);
}
// break out of while, only decrypt the first packet where we have a key
break;
@@ -614,12 +620,12 @@ 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);
decryptionResultBuilder.setEncrypted(true);
// 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);
if (!PgpSecurityConstants.isSecureSymmetricAlgorithm(symmetricEncryptionAlgo)) {
log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
decryptionResultBuilder.setInsecure(true);
}
JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
@@ -687,6 +693,13 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
}
// check for insecure signing key
// TODO: checks on signingRing ?
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
signatureResultBuilder.setInsecure(true);
}
dataChunk = plainFact.nextObject();
}
@@ -821,8 +834,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
// check for insecure hash algorithms
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
}
@@ -850,8 +863,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
// The MDC packet can be stripped by an attacker!
Log.d(Constants.TAG, "MDC fail");
if (!signatureResultBuilder.isValidSignature()) {
log.add(LogType.MSG_DC_ERROR_INTEGRITY_MISSING, indent);
decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE);
log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent);
decryptionResultBuilder.setInsecure(true);
}
}
@@ -864,7 +877,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
result.setCachedCryptoInputParcel(cryptoInput);
result.setSignatureResult(signatureResultBuilder.build());
result.setCharset(charset);
result.setDecryptionResult(decryptionResult);
result.setDecryptionResult(decryptionResultBuilder.build());
result.setDecryptionMetadata(metadata);
return result;
@@ -921,7 +934,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder);
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder, log, indent);
if (signature != null) {
try {
@@ -954,8 +967,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
// check for insecure hash algorithms
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
}
@@ -1013,7 +1026,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder);
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder, log, indent);
if (signature != null) {
updateProgress(R.string.progress_reading_data, 60, 100);
@@ -1056,8 +1069,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
// check for insecure hash algorithms
if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1);
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
signatureResultBuilder.setInsecure(true);
}
@@ -1076,7 +1089,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
private PGPSignature processPGPSignatureList(
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder)
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder,
OperationLog log, int indent)
throws PGPException {
CanonicalizedPublicKeyRing signingRing = null;
CanonicalizedPublicKey signingKey = null;
@@ -1118,6 +1132,13 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
}
// check for insecure signing key
// TODO: checks on signingRing ?
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
signatureResultBuilder.setInsecure(true);
}
return signature;
}

View File

@@ -316,14 +316,14 @@ public class PgpKeyOperation {
// Build key encrypter and decrypter based on passphrase
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
.build().get(PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO,
encryptorHashCalc, PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO,
encryptorHashCalc, PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
.build().get(PgpSecurityConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
sha1Calc, true, keyEncryptor);
@@ -1021,15 +1021,15 @@ public class PgpKeyOperation {
PGPSecretKey sKey; {
// Build key encrypter and decrypter based on passphrase
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
.build().get(PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
cryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
.build().get(PgpSecurityConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, sha1Calc, false, keyEncryptor);
}
@@ -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_BINDING_SIGNATURE_HASH_ALGO)
PgpSecurityConstants.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_BINDING_SIGNATURE_HASH_ALGO)
PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
{ // set subpackets
@@ -1280,13 +1280,13 @@ public class PgpKeyOperation {
OperationLog log, int indent) throws PGPException {
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
.get(PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// Build key encryptor based on new passphrase
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(newPassphrase.getCharArray());
// noinspection unchecked
@@ -1440,13 +1440,13 @@ public class PgpKeyOperation {
if (divertToCard) {
// use synchronous "NFC based" SignerBuilder
builder = new NfcSyncPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO,
pKey.getAlgorithm(), PgpSecurityConstants.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_BINDING_SIGNATURE_HASH_ALGO)
pKey.getAlgorithm(), PgpSecurityConstants.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.PREFERRED_SYMMETRIC_ALGORITHMS);
PgpSecurityConstants.PREFERRED_SYMMETRIC_ALGORITHMS);
hashedPacketsGen.setPreferredHashAlgorithms(false,
PgpConstants.PREFERRED_HASH_ALGORITHMS);
PgpSecurityConstants.PREFERRED_HASH_ALGORITHMS);
hashedPacketsGen.setPreferredCompressionAlgorithms(false,
PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS);
PgpSecurityConstants.PREFERRED_COMPRESSION_ALGORITHMS);
hashedPacketsGen.setPrimaryUserID(false, primary);
/* critical subpackets: we consider those important for a modern pgp implementation */

View File

@@ -0,0 +1,282 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.asn1.nist.NISTNamedCurves;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
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
*
* Extreme Decisions for Yahoo's End-to-End:
* https://github.com/yahoo/end-to-end/issues/31
* https://gist.github.com/coruus/68a8c65571e2b4225a69
*/
public class PgpSecurityConstants {
/*
* TODO:
* 1. Check binding signatures for requirements on import! throw out binding signatures with insecure
* signatures (bit length, hash algo)
*
* - put checks for curve OIDs and algorithm tags into import instead of PgpDecryptVerify?
* - check signingRing in PgpDecryptVerify?
* - ECC checks https://tools.ietf.org/html/rfc6637#section-13
* - check encryption algo used for encrypting secret keys?
* - check S2K security?
* - check for min rsa/dsa/elgamal/ecc requirements in key creation backend
*/
/**
* Whitelist of accepted symmetric encryption algorithms
* all other algorithms are rejected with OpenPgpDecryptionResult.RESULT_INSECURE
*/
private static HashSet<Integer> sSymmetricAlgorithmsWhitelist = new HashSet<>();
static {
// General remarks: We try to keep the whitelist short to reduce attack surface
// TODO: block IDEA?: Bad key schedule (weak keys), implementation difficulties (easy to make errors)
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.IDEA);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TRIPLE_DES); // a MUST in RFC
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.CAST5); // default in many gpg, pgp versions, 128 bit key
// BLOWFISH: Twofish is the successor
// SAFER: not used widely
// DES: < 128 bit security
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_128);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_192);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_256);
sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TWOFISH); // 128 bit
// CAMELLIA_128: not used widely
// CAMELLIA_192: not used widely
// CAMELLIA_256: not used widely
}
public static boolean isSecureSymmetricAlgorithm(int id) {
return sSymmetricAlgorithmsWhitelist.contains(id);
}
/**
* Whitelist of accepted hash algorithms
* all other algorithms are rejected with OpenPgpSignatureResult.RESULT_INSECURE
*
* coorus:
* Implementations SHOULD use SHA-512 for RSA or DSA signatures. They SHOULD NOT use SHA-384.
* ((cite to affine padding attacks; unproven status of RSA-PKCSv15))
*
* Implementations MUST NOT sign SHA-224 hashes. They SHOULD NOT accept signatures over SHA-224 hashes.
* ((collision resistance of 112-bits))
* Implementations SHOULD NOT sign SHA-256 hashes. They MUST NOT default to signing SHA-256 hashes.
*/
private static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>();
static {
// MD5: broken
// SHA1: broken
// RIPEMD160: same security properties as SHA1
// DOUBLE_SHA: not used widely
// MD2: not used widely
// TIGER_192: not used widely
// HAVAL_5_160: not used widely
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA256); // compatibility for old Mailvelope versions
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA384);
sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA512);
// SHA224: Not used widely, Yahoo argues against it
}
public static boolean isSecureHashAlgorithm(int id) {
return sHashAlgorithmsWhitelist.contains(id);
}
/**
* Whitelist of accepted asymmetric algorithms in switch statement
* all other algorithms are rejected with OpenPgpSignatureResult.RESULT_INSECURE or
* OpenPgpDecryptionResult.RESULT_INSECURE
*
* REASON:
* Don't allow ELGAMAL_GENERAL (20), reason in RFC
*
* coorus:
* Implementations MUST NOT accept, or treat any signature as valid, by an RSA key with
* bitlength less than 1023 bits.
* Implementations MUST NOT accept any RSA keys with bitlength less than 2047 bits after January 1, 2016.
*/
private static HashSet<String> sCurveWhitelist = new HashSet<>();
static {
sCurveWhitelist.add(NISTNamedCurves.getOID("P-256").getId());
sCurveWhitelist.add(NISTNamedCurves.getOID("P-384").getId());
sCurveWhitelist.add(NISTNamedCurves.getOID("P-521").getId());
}
public static boolean isSecureKey(CanonicalizedPublicKey key) {
switch (key.getAlgorithm()) {
case PublicKeyAlgorithmTags.RSA_GENERAL:
case PublicKeyAlgorithmTags.RSA_ENCRYPT:
case PublicKeyAlgorithmTags.RSA_SIGN: {
return (key.getBitStrength() >= 2048);
}
case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: {
return (key.getBitStrength() >= 2048);
}
case PublicKeyAlgorithmTags.DSA: {
return (key.getBitStrength() >= 2048);
}
case PublicKeyAlgorithmTags.ECDH:
case PublicKeyAlgorithmTags.ECDSA: {
return PgpSecurityConstants.sCurveWhitelist.contains(key.getCurveOid());
}
// ELGAMAL_GENERAL: Must not be used, use ELGAMAL_ENCRYPT
// DIFFIE_HELLMAN: unsure
default:
return false;
}
}
/**
* These array is written as a list of preferred encryption algorithms into keys created by us.
* Other implementations may choose to honor this selection.
* (Most preferred is first)
*
* REASON: See corresponding whitelist. AES received most cryptanalysis over the years
* and is still secure!
*/
public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
SymmetricKeyAlgorithmTags.AES_256,
SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128,
};
/**
* These array is written as a list of preferred hash algorithms into keys created by us.
* Other implementations may choose to honor this selection.
* (Most preferred is first)
*
* REASON: See corresponding whitelist. If possible use SHA-512, this is state of the art!
*/
public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
HashAlgorithmTags.SHA512,
};
/**
* These array is written as a list of preferred compression algorithms into keys created by us.
* Other implementations may choose to honor this selection.
* (Most preferred is first)
*
* REASON: See DEFAULT_COMPRESSION_ALGORITHM
*/
public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
CompressionAlgorithmTags.ZIP,
};
/**
* Hash algorithm used to certify public keys
*/
public static final int CERTIFY_HASH_ALGO = HashAlgorithmTags.SHA512;
/**
* Always use AES-256! We always ignore the preferred encryption algos of the recipient!
*
* coorus:
* Implementations SHOULD ignore the symmetric algorithm preferences of a recipient's public key;
* in particular, implementations MUST NOT choose an algorithm forbidden by this
* document because a recipient prefers it.
*
* NEEDCITE downgrade attacks on TLS, other protocols
*/
public static final int DEFAULT_SYMMETRIC_ALGORITHM = SymmetricKeyAlgorithmTags.AES_256;
public interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags {
int USE_DEFAULT = -1;
}
/**
* Always use SHA-512! We always ignore the preferred hash algos of the recipient!
*
* coorus:
* Implementations MUST ignore the hash algorithm preferences of a recipient when signing
* a message to a recipient. The difficulty of forging a signature under a given key,
* using generic attacks on hash functions, is the difficulty of the weakest hash signed by that key.
*
* Implementations MUST default to using SHA-512 for RSA signatures,
*
* and either SHA-512 or the matched instance of SHA-2 for ECDSA signatures.
* TODO: Ed25519
* CITE: zooko's hash function table CITE: distinguishers on SHA-256
*/
public static final int DEFAULT_HASH_ALGORITHM = HashAlgorithmTags.SHA512;
public interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags {
int USE_DEFAULT = -1;
}
/**
* Compression is disabled by default.
*
* The default compression algorithm is only used if explicitly enabled in the activity's
* overflow menu or via the OpenPGP API's extra OpenPgpApi.EXTRA_ENABLE_COMPRESSION
*
* REASON: Enabling compression can lead to a sidechannel. Consider a voting that is done via
* OpenPGP. Compression can lead to different ciphertext lengths based on the user's voting.
* This has happened in a voting done by Wikipedia (Google it).
*
* ZLIB: the format provides no benefits over DEFLATE, and is more malleable
* BZIP2: very slow
*/
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
* iterations are useful against offline attacks, as it takes more
* time to check each password. The actual number of iterations is
* rather complex, and also depends on the hash function in use.
* Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give
* you more iterations. As a rough rule of thumb, when using
* SHA256 as the hashing function, 0x10 gives you about 64
* iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0,
* or about 1 million iterations. The maximum you can go to is
* 0xff, or about 2 million iterations.
* from http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html
*
* Bouncy Castle default: 0x60
* kbsriram proposes: 0xc0
* Yahoo's End-to-End: 96 (65536 iterations) (https://github.com/yahoo/end-to-end/blob/master/src/javascript/crypto/e2e/openpgp/keyring.js)
*/
public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 96;
public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA512;
public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256;
public static final int SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA512;
// 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;
}

View File

@@ -33,10 +33,10 @@ public class PgpSignEncryptInputParcel implements Parcelable {
protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null;
protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
protected int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
protected int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
protected long mAdditionalEncryptId = Constants.key.none;
protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset;

View File

@@ -62,7 +62,6 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Set;
@@ -228,8 +227,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
// Use requested hash algo
int requestedAlgorithm = input.getSignatureHashAlgorithm();
if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
input.setSignatureHashAlgorithm(PgpConstants.DEFAULT_HASH_ALGORITHM);
if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
input.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
}
}
updateProgress(R.string.progress_preparing_streams, 2, 100);
@@ -240,8 +239,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
// Use requested encryption algo
int algo = input.getSymmetricEncryptionAlgorithm();
if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
algo = PgpConstants.DEFAULT_SYMMETRIC_ALGORITHM;
if (algo == PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
}
// has Integrity packet enabled!
JcePGPDataEncryptorBuilder encryptorBuilder =
@@ -337,8 +336,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
// Use preferred compression algo
int algo = input.getCompressionAlgorithm();
if (algo == PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpConstants.DEFAULT_COMPRESSION_ALGORITHM;
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
}
compressGen = new PGPCompressedDataGenerator(algo);
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));

View File

@@ -211,12 +211,19 @@ public class UncachedPublicKey {
return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT;
}
public boolean isRSA() {
return getAlgorithm() == PGPPublicKey.RSA_GENERAL
|| getAlgorithm() == PGPPublicKey.RSA_ENCRYPT
|| getAlgorithm() == PGPPublicKey.RSA_SIGN;
}
public boolean isDSA() {
return getAlgorithm() == PGPPublicKey.DSA;
}
public boolean isEC() {
return getAlgorithm() == PGPPublicKey.ECDH || getAlgorithm() == PGPPublicKey.ECDSA;
return getAlgorithm() == PGPPublicKey.ECDH
|| getAlgorithm() == PGPPublicKey.ECDSA;
}
public byte[] getFingerprint() {

View File

@@ -45,7 +45,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
@@ -1434,9 +1434,9 @@ public class ProviderHelper {
// DEPRECATED and thus hardcoded
values.put(KeychainContract.ApiAccounts.COMPRESSION, CompressionAlgorithmTags.ZLIB);
values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM,
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
values.put(KeychainContract.ApiAccounts.HASH_ALORITHM,
PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
return values;
}

View File

@@ -37,7 +37,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
@@ -248,7 +248,7 @@ public class OpenPgpService extends RemoteService {
.setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign)
.setVersionHeader(null)
.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
Intent signKeyIdIntent = getSignKeyMasterId(data);
// NOTE: Fallback to return account settings (Old API)
@@ -359,9 +359,9 @@ public class OpenPgpService extends RemoteService {
boolean enableCompression = data.getBooleanExtra(OpenPgpApi.EXTRA_ENABLE_COMPRESSION, true);
int compressionId;
if (enableCompression) {
compressionId = PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT;
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT;
} else {
compressionId = PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED;
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED;
}
// first try to get key ids from non-ambiguous key id extra
@@ -392,7 +392,7 @@ public class OpenPgpService extends RemoteService {
pseInput.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null)
.setCompressionAlgorithm(compressionId)
.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT)
.setSymmetricEncryptionAlgorithm(PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT)
.setEncryptionMasterKeyIds(keyIds)
.setFailOnMissingEncryptionKeyIds(true);
@@ -421,7 +421,7 @@ public class OpenPgpService extends RemoteService {
}
// sign and encrypt
pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT)
pseInput.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT)
.setAdditionalEncryptId(signKeyId); // add sign key for encryption
}

View File

@@ -50,12 +50,11 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@@ -554,17 +553,17 @@ public class EncryptFilesFragment
if (mUseCompression) {
data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else {
data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
}
data.setHiddenRecipients(mHiddenRecipients);
data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor);
data.setSymmetricEncryptionAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
EncryptActivity encryptActivity = (EncryptActivity) getActivity();
EncryptModeFragment modeFragment = encryptActivity.getModeFragment();

View File

@@ -33,12 +33,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
@@ -224,16 +223,16 @@ public class EncryptTextFragment
if (mUseCompression) {
data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else {
data.setCompressionAlgorithm(
PgpConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
}
data.setHiddenRecipients(mHiddenRecipients);
data.setSymmetricEncryptionAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm(
PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
// Always use armor for messages
data.setEnableAsciiArmorOutput(true);