Remove advanced preferences, move compression as menu item in encrypt activites, select hash and encryption algo based on hardcoded preferred lists
This commit is contained in:
@@ -177,52 +177,20 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all supported hash algorithms. This list is currently hardcoded to return
|
||||
* a limited set of algorithms supported by Yubikeys.
|
||||
*
|
||||
* TODO: look into preferred algos of this key?
|
||||
* Returns a list of all supported hash algorithms.
|
||||
*/
|
||||
public LinkedList<Integer> getSupportedHashAlgorithms() {
|
||||
LinkedList<Integer> supported = new LinkedList<>();
|
||||
|
||||
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
|
||||
// No support for MD5
|
||||
supported.add(HashAlgorithmTags.RIPEMD160);
|
||||
// don't allow SHA1
|
||||
supported.add(HashAlgorithmTags.SHA224);
|
||||
supported.add(HashAlgorithmTags.SHA384);
|
||||
supported.add(HashAlgorithmTags.SHA512);
|
||||
supported.add(HashAlgorithmTags.SHA256); // preferred is latest
|
||||
} else {
|
||||
// NOTE: List of hash algorithms OpenKeychain wants to support!
|
||||
|
||||
// don't allow MD5
|
||||
supported.add(HashAlgorithmTags.RIPEMD160);
|
||||
// don't allow SHA1
|
||||
supported.add(HashAlgorithmTags.SHA224);
|
||||
supported.add(HashAlgorithmTags.SHA384);
|
||||
supported.add(HashAlgorithmTags.SHA512);
|
||||
supported.add(HashAlgorithmTags.SHA256); // preferred is latest
|
||||
// some application don't support SHA512, thus preferred is SHA-256 (Mailvelope?)
|
||||
// TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS
|
||||
// choose best algo
|
||||
for (int currentInt : PgpConstants.PREFERRED_HASH_ALGORITHMS) {
|
||||
supported.add(currentInt);
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: look into preferred algos of this key?
|
||||
*/
|
||||
public static LinkedList<Integer> getSupportedEncryptionAlgorithms() {
|
||||
LinkedList<Integer> supported = new LinkedList<>();
|
||||
|
||||
supported.add(SymmetricKeyAlgorithmTags.TWOFISH);
|
||||
supported.add(SymmetricKeyAlgorithmTags.AES_128);
|
||||
supported.add(SymmetricKeyAlgorithmTags.AES_192);
|
||||
supported.add(SymmetricKeyAlgorithmTags.AES_256); // preferred is latest
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash,
|
||||
Date nfcCreationTimestamp) {
|
||||
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
|
||||
|
||||
@@ -47,26 +47,6 @@ public class PgpHelper {
|
||||
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
public static String getVersion(Context context) {
|
||||
String version;
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0);
|
||||
version = pi.versionName;
|
||||
return version;
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(Constants.TAG, "Version could not be retrieved!", e);
|
||||
return "0.0";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getVersionForHeader(Context context) {
|
||||
if(Preferences.getPreferences(context).getWriteVersionHeader()){
|
||||
return "OpenKeychain v" + getVersion(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes file securely by overwriting it with random data before deleting it.
|
||||
* <p/>
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||
import org.spongycastle.bcpg.sig.Features;
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
||||
@@ -90,49 +88,6 @@ public class PgpKeyOperation {
|
||||
private Stack<Progressable> mProgress;
|
||||
private AtomicBoolean mCancelled;
|
||||
|
||||
// most preferred is first
|
||||
private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{
|
||||
SymmetricKeyAlgorithmTags.AES_256,
|
||||
SymmetricKeyAlgorithmTags.AES_192,
|
||||
SymmetricKeyAlgorithmTags.AES_128,
|
||||
SymmetricKeyAlgorithmTags.TWOFISH
|
||||
};
|
||||
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
|
||||
HashAlgorithmTags.SHA512,
|
||||
HashAlgorithmTags.SHA384,
|
||||
HashAlgorithmTags.SHA256,
|
||||
HashAlgorithmTags.SHA224,
|
||||
HashAlgorithmTags.RIPEMD160
|
||||
};
|
||||
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
|
||||
CompressionAlgorithmTags.ZLIB,
|
||||
CompressionAlgorithmTags.BZIP2,
|
||||
CompressionAlgorithmTags.ZIP
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
* we use 0x90, a good trade-off between usability and security against offline attacks
|
||||
*/
|
||||
private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90;
|
||||
private static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256;
|
||||
private static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256;
|
||||
private static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256;
|
||||
|
||||
public PgpKeyOperation(Progressable progress) {
|
||||
super();
|
||||
if (progress != null) {
|
||||
@@ -346,14 +301,14 @@ public class PgpKeyOperation {
|
||||
|
||||
// Build key encrypter and decrypter based on passphrase
|
||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO,
|
||||
encryptorHashCalc, PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
|
||||
|
||||
// NOTE: only SHA1 is supported for key checksum calculations.
|
||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(HashAlgorithmTags.SHA1);
|
||||
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
||||
PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
||||
sha1Calc, true, keyEncryptor);
|
||||
|
||||
@@ -880,14 +835,14 @@ public class PgpKeyOperation {
|
||||
PGPSecretKey sKey; {
|
||||
// Build key encrypter and decrypter based on passphrase
|
||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||
|
||||
// NOTE: only SHA1 is supported for key checksum calculations.
|
||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(HashAlgorithmTags.SHA1);
|
||||
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
||||
sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, sha1Calc, false, keyEncryptor);
|
||||
}
|
||||
|
||||
@@ -1026,7 +981,8 @@ public class PgpKeyOperation {
|
||||
|
||||
// add packet with EMPTY notation data (updates old one, but will be stripped later)
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@@ -1052,7 +1008,8 @@ public class PgpKeyOperation {
|
||||
|
||||
// add packet with "pin" notation data
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@@ -1099,12 +1056,13 @@ public class PgpKeyOperation {
|
||||
OperationLog log, int indent) throws PGPException {
|
||||
|
||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
|
||||
.get(SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||
// Build key encryptor based on new passphrase
|
||||
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
|
||||
SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
newPassphrase.toCharArray());
|
||||
|
||||
@@ -1237,7 +1195,8 @@ public class PgpKeyOperation {
|
||||
int flags, long expiry)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
|
||||
@@ -1254,9 +1213,9 @@ public class PgpKeyOperation {
|
||||
* error than be ignored.
|
||||
*/
|
||||
/* non-critical subpackets: */
|
||||
hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredHashAlgorithms(false, PgpConstants.PREFERRED_HASH_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredCompressionAlgorithms(false, PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS);
|
||||
hashedPacketsGen.setPrimaryUserID(false, primary);
|
||||
|
||||
/* critical subpackets: we consider those important for a modern pgp implementation */
|
||||
@@ -1280,7 +1239,8 @@ public class PgpKeyOperation {
|
||||
PGPUserAttributeSubpacketVector vector)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
|
||||
@@ -1299,7 +1259,8 @@ public class PgpKeyOperation {
|
||||
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
@@ -1313,7 +1274,7 @@ public class PgpKeyOperation {
|
||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
@@ -1357,7 +1318,7 @@ public class PgpKeyOperation {
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
subHashedPacketsGen.setSignatureCreationTime(false, creationTime);
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
pKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
|
||||
@@ -1378,7 +1339,7 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey);
|
||||
|
||||
@@ -12,10 +12,10 @@ public class PgpSignEncryptInput {
|
||||
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
|
||||
protected long[] mEncryptionMasterKeyIds = null;
|
||||
protected String mSymmetricPassphrase = null;
|
||||
protected int mSymmetricEncryptionAlgorithm = Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
|
||||
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
|
||||
protected long mSignatureMasterKeyId = Constants.key.none;
|
||||
protected Long mSignatureSubKeyId = null;
|
||||
protected int mSignatureHashAlgorithm = Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
|
||||
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
|
||||
protected String mSignaturePassphrase = null;
|
||||
protected long mAdditionalEncryptId = Constants.key.none;
|
||||
protected byte[] mNfcSignedHash = null;
|
||||
|
||||
@@ -208,9 +208,9 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
// Use preferred hash algo
|
||||
int requestedAlgorithm = input.getSignatureHashAlgorithm();
|
||||
LinkedList<Integer> supported = signingKey.getSupportedHashAlgorithms();
|
||||
if (requestedAlgorithm == Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) {
|
||||
if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) {
|
||||
// get most preferred
|
||||
input.setSignatureHashAlgorithm(supported.getLast());
|
||||
input.setSignatureHashAlgorithm(supported.getFirst());
|
||||
} else if (!supported.contains(requestedAlgorithm)) {
|
||||
log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
@@ -224,9 +224,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
|
||||
// Use preferred encryption algo
|
||||
int algo = input.getSymmetricEncryptionAlgorithm();
|
||||
if (algo == Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) {
|
||||
if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) {
|
||||
// get most preferred
|
||||
algo = CanonicalizedSecretKey.getSupportedEncryptionAlgorithms().getLast();
|
||||
// TODO: get from recipients
|
||||
algo = PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS[0];
|
||||
}
|
||||
// has Integrity packet enabled!
|
||||
JcePGPDataEncryptorBuilder encryptorBuilder =
|
||||
|
||||
Reference in New Issue
Block a user