Better selection of preferred algorithm

This commit is contained in:
Dominik Schürmann 2015-03-05 10:49:57 +01:00
parent 8c8fdd6c49
commit c121657c2c
11 changed files with 99 additions and 40 deletions

View File

@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain;
import android.os.Environment; import android.os.Environment;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.jce.provider.BouncyCastleProvider;
import java.io.File; import java.io.File;
@ -82,11 +84,19 @@ public final class Constants {
public static final class Defaults { public static final class Defaults {
public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu"; public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu";
public static final int PREF_VERSION = 4; public static final int PREF_VERSION = 5;
} }
public static final class key { public static final class key {
public static final int none = 0; public static final int none = 0;
public static final int symmetric = -1; public static final int symmetric = -1;
} }
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;
}
} }

View File

@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.S2K; import org.spongycastle.bcpg.S2K;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKey;
@ -179,7 +180,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
* Returns a list of all supported hash algorithms. This list is currently hardcoded to return * Returns a list of all supported hash algorithms. This list is currently hardcoded to return
* a limited set of algorithms supported by Yubikeys. * a limited set of algorithms supported by Yubikeys.
* *
* @return * TODO: look into preferred algos of this key?
*/ */
public LinkedList<Integer> getSupportedHashAlgorithms() { public LinkedList<Integer> getSupportedHashAlgorithms() {
LinkedList<Integer> supported = new LinkedList<>(); LinkedList<Integer> supported = new LinkedList<>();
@ -187,24 +188,41 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
// No support for MD5 // No support for MD5
supported.add(HashAlgorithmTags.RIPEMD160); supported.add(HashAlgorithmTags.RIPEMD160);
supported.add(HashAlgorithmTags.SHA1); // don't allow SHA1
supported.add(HashAlgorithmTags.SHA224); supported.add(HashAlgorithmTags.SHA224);
supported.add(HashAlgorithmTags.SHA256);
supported.add(HashAlgorithmTags.SHA384); supported.add(HashAlgorithmTags.SHA384);
supported.add(HashAlgorithmTags.SHA512); // preferred is latest supported.add(HashAlgorithmTags.SHA512);
supported.add(HashAlgorithmTags.SHA256); // preferred is latest
} else { } else {
supported.add(HashAlgorithmTags.MD5); // NOTE: List of hash algorithms OpenKeychain wants to support!
// don't allow MD5
supported.add(HashAlgorithmTags.RIPEMD160); supported.add(HashAlgorithmTags.RIPEMD160);
supported.add(HashAlgorithmTags.SHA1); // don't allow SHA1
supported.add(HashAlgorithmTags.SHA224); supported.add(HashAlgorithmTags.SHA224);
supported.add(HashAlgorithmTags.SHA256);
supported.add(HashAlgorithmTags.SHA384); supported.add(HashAlgorithmTags.SHA384);
supported.add(HashAlgorithmTags.SHA512); // preferred is latest supported.add(HashAlgorithmTags.SHA512);
supported.add(HashAlgorithmTags.SHA256); // preferred is latest
// some application don't support SHA512, thus preferred is SHA-256 (Mailvelope?)
} }
return supported; 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, private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash,
Date nfcCreationTimestamp) { Date nfcCreationTimestamp) {
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {

View File

@ -19,11 +19,11 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.IterableIterator;
@ -45,7 +45,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
public CanonicalizedSecretKeyRing(byte[] blob, boolean isRevoked, int verified) public CanonicalizedSecretKeyRing(byte[] blob, boolean isRevoked, int verified)
{ {
super(verified); super(verified);
PGPObjectFactory factory = new PGPObjectFactory(blob); JcaPGPObjectFactory factory = new JcaPGPObjectFactory(blob);
PGPKeyRing keyRing = null; PGPKeyRing keyRing = null;
try { try {
if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) { if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) {

View File

@ -95,7 +95,7 @@ public class PgpKeyOperation {
SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_256,
SymmetricKeyAlgorithmTags.AES_192, SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.AES_128,
SymmetricKeyAlgorithmTags.CAST5 SymmetricKeyAlgorithmTags.TWOFISH
}; };
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
HashAlgorithmTags.SHA512, HashAlgorithmTags.SHA512,

View File

@ -12,10 +12,10 @@ public class PgpSignEncryptInput {
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null; protected long[] mEncryptionMasterKeyIds = null;
protected String mSymmetricPassphrase = null; protected String mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = 0; protected int mSymmetricEncryptionAlgorithm = Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
protected long mSignatureMasterKeyId = Constants.key.none; protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null; protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = 0; protected int mSignatureHashAlgorithm = Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
protected String mSignaturePassphrase = null; protected String mSignaturePassphrase = null;
protected long mAdditionalEncryptId = Constants.key.none; protected long mAdditionalEncryptId = Constants.key.none;
protected byte[] mNfcSignedHash = null; protected byte[] mNfcSignedHash = null;

View File

@ -25,7 +25,6 @@ import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.BCPGOutputStream; import org.spongycastle.bcpg.BCPGOutputStream;
import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.openpgp.PGPCompressedDataGenerator; import org.spongycastle.openpgp.PGPCompressedDataGenerator;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPEncryptedDataGenerator; import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData; import org.spongycastle.openpgp.PGPLiteralData;
@ -206,10 +205,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
} }
// check if hash algo is supported // Use preferred hash algo
int requestedAlgorithm = input.getSignatureHashAlgorithm(); int requestedAlgorithm = input.getSignatureHashAlgorithm();
LinkedList<Integer> supported = signingKey.getSupportedHashAlgorithms(); LinkedList<Integer> supported = signingKey.getSupportedHashAlgorithms();
if (requestedAlgorithm == 0) { if (requestedAlgorithm == Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) {
// get most preferred // get most preferred
input.setSignatureHashAlgorithm(supported.getLast()); input.setSignatureHashAlgorithm(supported.getLast());
} else if (!supported.contains(requestedAlgorithm)) { } else if (!supported.contains(requestedAlgorithm)) {
@ -222,9 +221,12 @@ public class PgpSignEncryptOperation extends BaseOperation {
/* Initialize PGPEncryptedDataGenerator for later usage */ /* Initialize PGPEncryptedDataGenerator for later usage */
PGPEncryptedDataGenerator cPk = null; PGPEncryptedDataGenerator cPk = null;
if (enableEncryption) { if (enableEncryption) {
// Use preferred encryption algo
int algo = input.getSymmetricEncryptionAlgorithm(); int algo = input.getSymmetricEncryptionAlgorithm();
if (algo == 0) { if (algo == Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) {
algo = PGPEncryptedData.AES_128; // get most preferred
algo = CanonicalizedSecretKey.getSupportedEncryptionAlgorithms().getLast();
} }
// has Integrity packet enabled! // has Integrity packet enabled!
JcePGPDataEncryptorBuilder encryptorBuilder = JcePGPDataEncryptorBuilder encryptorBuilder =

View File

@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -259,7 +260,7 @@ public class OpenPgpService extends RemoteService {
.setCleartextSignature(cleartextSign) .setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign) .setDetachedSignature(!cleartextSign)
.setVersionHeader(PgpHelper.getVersionForHeader(this)) .setVersionHeader(PgpHelper.getVersionForHeader(this))
.setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) .setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignatureMasterKeyId(accSettings.getKeyId()) .setSignatureMasterKeyId(accSettings.getKeyId())
.setNfcState(nfcSignedHash, nfcCreationDate); .setNfcState(nfcSignedHash, nfcCreationDate);
@ -357,8 +358,8 @@ public class OpenPgpService extends RemoteService {
PgpSignEncryptInput pseInput = new PgpSignEncryptInput(); PgpSignEncryptInput pseInput = new PgpSignEncryptInput();
pseInput.setEnableAsciiArmorOutput(asciiArmor) pseInput.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(PgpHelper.getVersionForHeader(this)) .setVersionHeader(PgpHelper.getVersionForHeader(this))
.setCompressionId(accSettings.getCompression()) .setCompressionId(Preferences.getPreferences(this).getDefaultFileCompression())
.setSymmetricEncryptionAlgorithm(accSettings.getEncryptionAlgorithm()) .setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
.setEncryptionMasterKeyIds(keyIds) .setEncryptionMasterKeyIds(keyIds)
.setFailOnMissingEncryptionKeyIds(true) .setFailOnMissingEncryptionKeyIds(true)
.setAdditionalEncryptId(accSettings.getKeyId()); // add acc key for encryption .setAdditionalEncryptId(accSettings.getKeyId()); // add acc key for encryption
@ -374,7 +375,7 @@ public class OpenPgpService extends RemoteService {
} }
// sign and encrypt // sign and encrypt
pseInput.setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) pseInput.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignatureMasterKeyId(accSettings.getKeyId()) .setSignatureMasterKeyId(accSettings.getKeyId())
.setNfcState(nfcSignedHash, nfcCreationDate); .setNfcState(nfcSignedHash, nfcCreationDate);
} }

View File

@ -197,6 +197,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
data.addOutputUris(mOutputUris); data.addOutputUris(mOutputUris);
data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm());
data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm());
// Always use armor for messages // Always use armor for messages
data.setEnableAsciiArmorOutput(mUseArmor); data.setEnableAsciiArmorOutput(mUseArmor);

View File

@ -190,6 +190,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
data.setCleartextSignature(true); data.setCleartextSignature(true);
data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm());
data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm());
// Always use armor for messages // Always use armor for messages
data.setEnableAsciiArmorOutput(true); data.setEnableAsciiArmorOutput(true);

View File

@ -33,8 +33,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference; import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
@ -345,12 +343,20 @@ public class SettingsActivity extends PreferenceActivity {
} }
private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) { private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) {
int valueIds[] = {PGPEncryptedData.AES_128, PGPEncryptedData.AES_192, int valueIds[] = {
PGPEncryptedData.AES_256, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH, Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED,
PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES, Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_256,
PGPEncryptedData.IDEA,}; Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_192,
String entries[] = {"AES-128", "AES-192", "AES-256", "Blowfish", "Twofish", "CAST5", Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128,
"DES", "Triple DES", "IDEA",}; Constants.OpenKeychainSymmetricKeyAlgorithmTags.TWOFISH,
};
String entries[] = {
"Use preferred algorithm",
"AES-256",
"AES-192",
"AES-128",
"Twofish",
};
String values[] = new String[valueIds.length]; String values[] = new String[valueIds.length];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = "" + valueIds[i]; values[i] = "" + valueIds[i];
@ -372,11 +378,21 @@ public class SettingsActivity extends PreferenceActivity {
} }
private static void initializeHashAlgorithm(final IntegerListPreference mHashAlgorithm) { private static void initializeHashAlgorithm(final IntegerListPreference mHashAlgorithm) {
int[] valueIds = new int[]{HashAlgorithmTags.RIPEMD160, int[] valueIds = new int[]{
HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256, Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED,
HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512,}; Constants.OpenKeychainHashAlgorithmTags.SHA512,
String[] entries = new String[]{"RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384", Constants.OpenKeychainHashAlgorithmTags.SHA384,
"SHA-512",}; Constants.OpenKeychainHashAlgorithmTags.SHA256,
Constants.OpenKeychainHashAlgorithmTags.SHA224,
Constants.OpenKeychainHashAlgorithmTags.RIPEMD160,
};
String[] entries = new String[]{
"Use preferred algorithm",
"SHA-512",
"SHA-384",
"SHA-256",
"SHA-224",
"RIPEMD-160"};
String[] values = new String[valueIds.length]; String[] values = new String[valueIds.length];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = "" + valueIds[i]; values[i] = "" + valueIds[i];

View File

@ -210,6 +210,7 @@ public class Preferences {
} }
return servers.toArray(chunks); return servers.toArray(chunks);
} }
public String getPreferredKeyserver() { public String getPreferredKeyserver() {
return getKeyServers()[0]; return getKeyServers()[0];
} }
@ -246,6 +247,7 @@ public class Preferences {
editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver); editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver);
editor.commit(); editor.commit();
} }
public void setSearchKeybase(boolean searchKeybase) { public void setSearchKeybase(boolean searchKeybase) {
SharedPreferences.Editor editor = mSharedPreferences.edit(); SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase); editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase);
@ -322,6 +324,12 @@ public class Preferences {
setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); setDefaultHashAlgorithm(HashAlgorithmTags.SHA256);
} }
} }
// fall through
case 5: {
// use preferred hash and encryption algo setting
setDefaultHashAlgorithm(Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED);
setDefaultEncryptionAlgorithm(Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
}
} }
// write new preference version // write new preference version