From e72e47d92ec957d42c04bf8b1e0dd8e8b641cd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 15:24:37 +0200 Subject: Remove support for v3 sig generation --- .../org/sufficientlysecure/keychain/Constants.java | 1 - .../keychain/helper/Preferences.java | 10 --- .../keychain/pgp/PgpSignEncrypt.java | 90 +++------------------- .../keychain/remote/OpenPgpService.java | 2 - .../keychain/service/KeychainIntentService.java | 1 - .../keychain/ui/PreferencesActivity.java | 18 ----- 6 files changed, 10 insertions(+), 112 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index f240b5cc2..755d74ac2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -64,7 +64,6 @@ public final class Constants { public static final String DEFAULT_FILE_COMPRESSION = "defaultFileCompression"; public static final String PASSPHRASE_CACHE_TTL = "passphraseCacheTtl"; public static final String LANGUAGE = "language"; - public static final String FORCE_V3_SIGNATURES = "forceV3Signatures"; public static final String KEY_SERVERS = "keyServers"; public static final String KEY_SERVERS_DEFAULT_VERSION = "keyServersDefaultVersion"; public static final String WRITE_VERSION_HEADER = "writeVersionHeader"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index a0bac80aa..72e88d793 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -130,16 +130,6 @@ public class Preferences { editor.commit(); } - public boolean getForceV3Signatures() { - return mSharedPreferences.getBoolean(Constants.Pref.FORCE_V3_SIGNATURES, false); - } - - public void setForceV3Signatures(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.FORCE_V3_SIGNATURES, value); - editor.commit(); - } - public boolean isFirstTime() { return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index b0e546662..263b0c5bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -27,7 +27,6 @@ import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPLiteralData; import org.spongycastle.openpgp.PGPLiteralDataGenerator; import org.spongycastle.openpgp.PGPSignatureGenerator; -import org.spongycastle.openpgp.PGPV3SignatureGenerator; import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator; import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; import org.sufficientlysecure.keychain.Constants; @@ -68,7 +67,6 @@ public class PgpSignEncrypt { private int mSymmetricEncryptionAlgorithm; private long mSignatureMasterKeyId; private int mSignatureHashAlgorithm; - private boolean mSignatureForceV3; private String mSignaturePassphrase; private boolean mEncryptToSigner; private boolean mCleartextInput; @@ -99,7 +97,6 @@ public class PgpSignEncrypt { this.mSymmetricEncryptionAlgorithm = builder.mSymmetricEncryptionAlgorithm; this.mSignatureMasterKeyId = builder.mSignatureMasterKeyId; this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm; - this.mSignatureForceV3 = builder.mSignatureForceV3; this.mSignaturePassphrase = builder.mSignaturePassphrase; this.mEncryptToSigner = builder.mEncryptToSigner; this.mCleartextInput = builder.mCleartextInput; @@ -122,7 +119,6 @@ public class PgpSignEncrypt { private int mSymmetricEncryptionAlgorithm = 0; private long mSignatureMasterKeyId = Constants.key.none; private int mSignatureHashAlgorithm = 0; - private boolean mSignatureForceV3 = false; private String mSignaturePassphrase = null; private boolean mEncryptToSigner = false; private boolean mCleartextInput = false; @@ -179,11 +175,6 @@ public class PgpSignEncrypt { return this; } - public Builder setSignatureForceV3(boolean signatureForceV3) { - mSignatureForceV3 = signatureForceV3; - return this; - } - public Builder setSignaturePassphrase(String signaturePassphrase) { mSignaturePassphrase = signaturePassphrase; return this; @@ -349,19 +340,13 @@ public class PgpSignEncrypt { /* Initialize signature generator object for later usage */ PGPSignatureGenerator signatureGenerator = null; - PGPV3SignatureGenerator signatureV3Generator = null; if (enableSignature) { updateProgress(R.string.progress_preparing_signature, 4, 100); try { boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption; - if (mSignatureForceV3) { - signatureV3Generator = signingKey.getV3SignatureGenerator( - mSignatureHashAlgorithm, cleartext); - } else { - signatureGenerator = signingKey.getSignatureGenerator( - mSignatureHashAlgorithm, cleartext); - } + signatureGenerator = signingKey.getSignatureGenerator( + mSignatureHashAlgorithm, cleartext); } catch (PgpGeneralException e) { // TODO throw correct type of exception (which shouldn't be PGPException) throw new KeyExtractionException(); @@ -388,11 +373,7 @@ public class PgpSignEncrypt { } if (enableSignature) { - if (mSignatureForceV3) { - signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut); - } else { - signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); - } + signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); } PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); @@ -408,11 +389,7 @@ public class PgpSignEncrypt { // update signature buffer if signature is requested if (enableSignature) { - if (mSignatureForceV3) { - signatureV3Generator.update(buffer, 0, length); - } else { - signatureGenerator.update(buffer, 0, length); - } + signatureGenerator.update(buffer, 0, length); } alreadyWritten += length; @@ -435,11 +412,7 @@ public class PgpSignEncrypt { final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // update signature buffer with first line - if (mSignatureForceV3) { - processLineV3(reader.readLine(), armorOut, signatureV3Generator); - } else { - processLine(reader.readLine(), armorOut, signatureGenerator); - } + processLine(reader.readLine(), armorOut, signatureGenerator); // TODO: progress: fake annealing? while (true) { @@ -454,13 +427,8 @@ public class PgpSignEncrypt { armorOut.write(NEW_LINE); // update signature buffer with input line - if (mSignatureForceV3) { - signatureV3Generator.update(NEW_LINE); - processLineV3(line, armorOut, signatureV3Generator); - } else { - signatureGenerator.update(NEW_LINE); - processLine(line, armorOut, signatureGenerator); - } + signatureGenerator.update(NEW_LINE); + processLine(line, armorOut, signatureGenerator); } armorOut.endClearText(); @@ -480,11 +448,7 @@ public class PgpSignEncrypt { bcpgOut = new BCPGOutputStream(out); } - if (mSignatureForceV3) { - signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut); - } else { - signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); - } + signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), @@ -496,11 +460,7 @@ public class PgpSignEncrypt { while ((length = in.read(buffer)) > 0) { pOut.write(buffer, 0, length); - if (mSignatureForceV3) { - signatureV3Generator.update(buffer, 0, length); - } else { - signatureGenerator.update(buffer, 0, length); - } + signatureGenerator.update(buffer, 0, length); alreadyWritten += length; if (mData.getSize() > 0) { @@ -517,11 +477,7 @@ public class PgpSignEncrypt { if (enableSignature) { updateProgress(R.string.progress_generating_signature, 95, 100); - if (mSignatureForceV3) { - signatureV3Generator.generate().encode(pOut); - } else { - signatureGenerator.generate().encode(pOut); - } + signatureGenerator.generate().encode(pOut); } // closing outputs @@ -570,30 +526,4 @@ public class PgpSignEncrypt { pSignatureGenerator.update(data); } - private static void processLineV3(final String pLine, final ArmoredOutputStream pArmoredOutput, - final PGPV3SignatureGenerator pSignatureGenerator) - throws IOException, SignatureException { - - if (pLine == null) { - return; - } - - final char[] chars = pLine.toCharArray(); - int len = chars.length; - - while (len > 0) { - if (!Character.isWhitespace(chars[len - 1])) { - break; - } - len--; - } - - final byte[] data = pLine.substring(0, len).getBytes("UTF-8"); - - if (pArmoredOutput != null) { - pArmoredOutput.write(data); - } - pSignatureGenerator.update(data); - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 492ade7c3..3541dad98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -191,7 +191,6 @@ public class OpenPgpService extends RemoteService { builder.setEnableAsciiArmorOutput(asciiArmor) .setVersionHeader(PgpHelper.getVersionForHeader(this)) .setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) - .setSignatureForceV3(false) .setSignatureMasterKeyId(accSettings.getKeyId()) .setSignaturePassphrase(passphrase); @@ -299,7 +298,6 @@ public class OpenPgpService extends RemoteService { // sign and encrypt builder.setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) - .setSignatureForceV3(false) .setSignatureMasterKeyId(accSettings.getKeyId()) .setSignaturePassphrase(passphrase); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d1d848066..d6c470e11 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -257,7 +257,6 @@ public class KeychainIntentService extends IntentService .setCompressionId(compressionId) .setSymmetricEncryptionAlgorithm( Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) - .setSignatureForceV3(Preferences.getPreferences(this).getForceV3Signatures()) .setEncryptionMasterKeyIds(encryptionKeyIds) .setSymmetricPassphrase(symmetricPassphrase) .setSignatureMasterKeyId(signatureKeyId) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java index 5bef6cc9f..de3236d35 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java @@ -119,9 +119,6 @@ public class PreferencesActivity extends PreferenceActivity { initializeAsciiArmor( (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR)); - initializeForceV3Signatures( - (CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES)); - initializeWriteVersionHeader( (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER)); @@ -266,9 +263,6 @@ public class PreferencesActivity extends PreferenceActivity { initializeAsciiArmor( (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR)); - initializeForceV3Signatures( - (CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES)); - initializeWriteVersionHeader( (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER)); } @@ -392,18 +386,6 @@ public class PreferencesActivity extends PreferenceActivity { }); } - private static void initializeForceV3Signatures(final CheckBoxPreference mForceV3Signatures) { - mForceV3Signatures.setChecked(sPreferences.getForceV3Signatures()); - mForceV3Signatures - .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mForceV3Signatures.setChecked((Boolean) newValue); - sPreferences.setForceV3Signatures((Boolean) newValue); - return false; - } - }); - } - private static void initializeWriteVersionHeader(final CheckBoxPreference mWriteVersionHeader) { mWriteVersionHeader.setChecked(sPreferences.getWriteVersionHeader()); mWriteVersionHeader.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { -- cgit v1.2.3 From 225e2482935fbe93147303654f09536b605eac96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 15:30:08 +0200 Subject: Remove MD5 support --- .../java/org/sufficientlysecure/keychain/helper/Preferences.java | 5 +++++ .../java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java | 4 ++-- .../java/org/sufficientlysecure/keychain/util/AlgorithmNames.java | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index 72e88d793..80b047530 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -193,6 +193,11 @@ public class Preferences { if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, 0) == 0x21070001) { setDefaultFileCompression(CompressionAlgorithmTags.UNCOMPRESSED); } + + // migrate away from MD5 + if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) == HashAlgorithmTags.MD5) { + setDefaultHashAlgorithm(HashAlgorithmTags.SHA512); + } } public void setWriteVersionHeader(boolean conceal) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java index de3236d35..64c1e16be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java @@ -317,10 +317,10 @@ public class PreferencesActivity extends PreferenceActivity { private static void initializeHashAlgorithm (final IntegerListPreference mHashAlgorithm, int[] valueIds, String[] entries, String[] values) { - valueIds = new int[]{HashAlgorithmTags.MD5, HashAlgorithmTags.RIPEMD160, + valueIds = new int[]{HashAlgorithmTags.RIPEMD160, HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256, HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512,}; - entries = new String[]{"MD5", "RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384", + entries = new String[]{"RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512",}; values = new String[valueIds.length]; for (int i = 0; i < values.length; ++i) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java index 9acc7a73b..99db634ac 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java @@ -50,7 +50,6 @@ public class AlgorithmNames { mEncryptionNames.put(PGPEncryptedData.TRIPLE_DES, "Triple DES"); mEncryptionNames.put(PGPEncryptedData.IDEA, "IDEA"); - mHashNames.put(HashAlgorithmTags.MD5, "MD5"); mHashNames.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160"); mHashNames.put(HashAlgorithmTags.SHA1, "SHA-1"); mHashNames.put(HashAlgorithmTags.SHA224, "SHA-224"); -- cgit v1.2.3 From 0a1de8deeaa543f3a0658c3927fd632d115e34fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 15:42:02 +0200 Subject: Do not import v3 keys, they are insecure! --- .../org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 4 ++++ .../sufficientlysecure/keychain/provider/ProviderHelper.java | 10 ++++++++++ .../keychain/service/OperationResultParcel.java | 1 + 3 files changed, 15 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 73a51942d..18f27cbff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -118,6 +118,10 @@ public class UncachedKeyRing { return mRing.getPublicKey().getFingerprint(); } + public int getVersion() { + return mRing.getPublicKey().getVersion(); + } + public static UncachedKeyRing decodeFromData(byte[] data) throws PgpGeneralException, IOException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index a13bb9c98..f8b2e549f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -642,6 +642,11 @@ public class ProviderHelper { log(LogLevel.START, LogType.MSG_IP, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; + if (publicRing.getVersion() <= 3) { + log(LogLevel.ERROR, LogType.MSG_IP_V3_KEY); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + } + if (publicRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); @@ -734,6 +739,11 @@ public class ProviderHelper { log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; + if (secretRing.getVersion() <= 3) { + log(LogLevel.ERROR, LogType.MSG_IP_V3_KEY); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + } + if ( ! secretRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index d7d98fd68..93c3fc42b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -231,6 +231,7 @@ public class OperationResultParcel implements Parcelable { MSG_IP(R.string.msg_ip), MSG_IP_APPLY_BATCH (R.string.msg_ip_apply_batch), MSG_IP_BAD_TYPE_SECRET (R.string.msg_ip_bad_type_secret), + MSG_IP_V3_KEY (R.string.msg_ip_v3_key), MSG_IP_DELETE_OLD_FAIL (R.string.msg_ip_delete_old_fail), MSG_IP_DELETE_OLD_OK (R.string.msg_ip_delete_old_ok), MSG_IP_ENCODE_FAIL (R.string.msg_ip_encode_fail), -- cgit v1.2.3 From 62f7bf62150b460ee2dfa14f2c45f6df40d55cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 15:58:26 +0200 Subject: move v3 key import prevention into canonicalization method --- .../org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 7 +++++++ .../sufficientlysecure/keychain/provider/ProviderHelper.java | 10 ---------- .../keychain/service/OperationResultParcel.java | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 18f27cbff..5c8a85de9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; +import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -245,6 +246,12 @@ public class UncachedKeyRing { indent, PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())); indent += 1; + // do not accept v3 keys + if (getVersion() <= 3) { + log.add(LogLevel.ERROR, LogType.MSG_KC_V3_KEY, indent); + return null; + } + final Date now = new Date(); int redundantCerts = 0, badCerts = 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index f8b2e549f..a13bb9c98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -642,11 +642,6 @@ public class ProviderHelper { log(LogLevel.START, LogType.MSG_IP, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; - if (publicRing.getVersion() <= 3) { - log(LogLevel.ERROR, LogType.MSG_IP_V3_KEY); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); - } - if (publicRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); @@ -739,11 +734,6 @@ public class ProviderHelper { log(LogLevel.START, LogType.MSG_IS, PgpKeyHelper.convertKeyIdToHex(masterKeyId)); mIndent += 1; - if (secretRing.getVersion() <= 3) { - log(LogLevel.ERROR, LogType.MSG_IP_V3_KEY); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); - } - if ( ! secretRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 93c3fc42b..25dac2139 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -231,7 +231,6 @@ public class OperationResultParcel implements Parcelable { MSG_IP(R.string.msg_ip), MSG_IP_APPLY_BATCH (R.string.msg_ip_apply_batch), MSG_IP_BAD_TYPE_SECRET (R.string.msg_ip_bad_type_secret), - MSG_IP_V3_KEY (R.string.msg_ip_v3_key), MSG_IP_DELETE_OLD_FAIL (R.string.msg_ip_delete_old_fail), MSG_IP_DELETE_OLD_OK (R.string.msg_ip_delete_old_ok), MSG_IP_ENCODE_FAIL (R.string.msg_ip_encode_fail), @@ -290,6 +289,7 @@ public class OperationResultParcel implements Parcelable { MSG_IS_SUCCESS (R.string.msg_is_success), // keyring canonicalization + MSG_KC_V3_KEY (R.string.msg_kc_v3_key), MSG_KC_PUBLIC (R.string.msg_kc_public), MSG_KC_SECRET (R.string.msg_kc_secret), MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid), -- cgit v1.2.3 From ef2449917e53e312ebc2eb4bea7e3149ba9db137 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 12:22:02 +0200 Subject: factor KeySpinner out --- .../keychain/ui/EncryptAsymmetricFragment.java | 142 +---------------- .../ui/widget/EncryptKeyCompletionView.java | 4 +- .../keychain/ui/widget/KeySpinner.java | 171 +++++++++++++++++++++ .../keychain/ui/widget/SignKeySpinner.java | 48 ++++++ 4 files changed, 229 insertions(+), 136 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index a402b6f68..41566cffc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; +import org.sufficientlysecure.keychain.ui.widget.KeySpinner; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; @@ -54,22 +55,20 @@ import java.util.Iterator; import java.util.List; public class EncryptAsymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { - public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; - public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids"; - ProviderHelper mProviderHelper; // view - private Spinner mSign; + private KeySpinner mSign; private EncryptKeyCompletionView mEncryptKeyView; - private SelectSignKeyCursorAdapter mSignAdapter = new SelectSignKeyCursorAdapter(); // model private EncryptActivityInterface mEncryptInterface; @Override public void onNotifyUpdate() { - + if (mSign != null) { + mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey()); + } } @Override @@ -101,8 +100,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSign = (Spinner) view.findViewById(R.id.sign); - mSign.setAdapter(mSignAdapter); + mSign = (KeySpinner) view.findViewById(R.id.sign); mSign.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { @@ -128,42 +126,6 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi // preselect keys given preselectKeys(); - getLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks() { - @Override - public Loader onCreateLoader(int id, Bundle args) { - // This is called when a new Loader needs to be created. This - // sample only has one Loader, so we don't care about the ID. - Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); - - // These are the rows that we will retrieve. - String[] projection = new String[]{ - KeyRings._ID, - KeyRings.MASTER_KEY_ID, - KeyRings.KEY_ID, - KeyRings.USER_ID, - KeyRings.IS_EXPIRED, - KeyRings.HAS_SIGN, - KeyRings.HAS_ANY_SECRET - }; - - String where = KeyRings.HAS_ANY_SECRET + " = 1 AND " + KeyRings.HAS_SIGN + " NOT NULL AND " - + KeyRings.IS_REVOKED + " = 0 AND " + KeyRings.IS_EXPIRED + " = 0"; - - // Now create and return a CursorLoader that will take care of - // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, projection, where, null, null); - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - mSignAdapter.swapCursor(data); - } - - @Override - public void onLoaderReset(Loader loader) { - mSignAdapter.swapCursor(null); - } - }); mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { @Override public void onTokenAdded(Object token) { @@ -194,6 +156,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi KeyRings.buildUnifiedKeyRingUri(signatureKey)); if(keyring.hasAnySecret()) { setSignatureKeyId(keyring.getMasterKeyId()); + mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey()); } } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); @@ -233,95 +196,4 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi setEncryptionKeyIds(keyIdsArr); setEncryptionUserIds(userIds.toArray(new String[userIds.size()])); } - - private class SelectSignKeyCursorAdapter extends BaseAdapter implements SpinnerAdapter { - private CursorAdapter inner; - private int mIndexUserId; - private int mIndexKeyId; - private int mIndexMasterKeyId; - - public SelectSignKeyCursorAdapter() { - inner = new CursorAdapter(null, null, 0) { - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return getActivity().getLayoutInflater().inflate(R.layout.encrypt_asymmetric_signkey, null); - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); - ((TextView) view.findViewById(android.R.id.title)).setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")")); - ((TextView) view.findViewById(android.R.id.text1)).setText(userId[1]); - ((TextView) view.findViewById(android.R.id.text2)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); - } - - @Override - public long getItemId(int position) { - mCursor.moveToPosition(position); - return mCursor.getLong(mIndexMasterKeyId); - } - }; - } - - public Cursor swapCursor(Cursor newCursor) { - if (newCursor == null) return inner.swapCursor(null); - - mIndexKeyId = newCursor.getColumnIndex(KeyRings.KEY_ID); - mIndexUserId = newCursor.getColumnIndex(KeyRings.USER_ID); - mIndexMasterKeyId = newCursor.getColumnIndex(KeyRings.MASTER_KEY_ID); - if (newCursor.moveToFirst()) { - do { - if (newCursor.getLong(mIndexMasterKeyId) == mEncryptInterface.getSignatureKey()) { - mSign.setSelection(newCursor.getPosition() + 1); - } - } while (newCursor.moveToNext()); - } - return inner.swapCursor(newCursor); - } - - @Override - public int getCount() { - return inner.getCount() + 1; - } - - @Override - public Object getItem(int position) { - if (position == 0) return null; - return inner.getItem(position - 1); - } - - @Override - public long getItemId(int position) { - if (position == 0) return Constants.key.none; - return inner.getItemId(position - 1); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View v = getDropDownView(position, convertView, parent); - v.findViewById(android.R.id.text1).setVisibility(View.GONE); - return v; - } - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - View v; - if (position == 0) { - if (convertView == null) { - v = inner.newView(null, null, parent); - } else { - v = convertView; - } - ((TextView) v.findViewById(android.R.id.title)).setText("None"); - v.findViewById(android.R.id.text1).setVisibility(View.GONE); - v.findViewById(android.R.id.text2).setVisibility(View.GONE); - } else { - v = inner.getView(position - 1, convertView, parent); - v.findViewById(android.R.id.text1).setVisibility(View.VISIBLE); - v.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); - } - return v; - } - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 20b9570bb..ceb3f665f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -111,7 +111,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { protected void onAttachedToWindow() { super.onAttachedToWindow(); if (getContext() instanceof FragmentActivity) { - ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { + ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(hashCode(), null, new LoaderManager.LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { // These are the rows that we will retrieve. @@ -143,6 +143,8 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { swapCursor(null); } }); + } else { + Log.e(Constants.TAG, "EncryptKeyCompletionView must be attached to a FragmentActivity, this is " + getContext().getClass()); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java new file mode 100644 index 000000000..b8d83311a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -0,0 +1,171 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.content.Context; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; +import android.support.v4.widget.CursorAdapter; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.util.Log; + +public abstract class KeySpinner extends Spinner { + private long mSelectedKeyId; + private SelectKeyAdapter mAdapter = new SelectKeyAdapter(); + + public KeySpinner(Context context) { + super(context); + } + + public KeySpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public KeySpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public abstract Loader onCreateLoader(); + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setAdapter(mAdapter); + if (getContext() instanceof FragmentActivity) { + ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(hashCode(), null, new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + return KeySpinner.this.onCreateLoader(); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mAdapter.swapCursor(null); + } + }); + } else { + Log.e(Constants.TAG, "KeySpinner must be attached to FragmentActivity, this is " + getContext().getClass()); + } + } + + public long getSelectedKeyId() { + return mSelectedKeyId; + } + + public void setSelectedKeyId(long selectedKeyId) { + this.mSelectedKeyId = selectedKeyId; + } + + private class SelectKeyAdapter extends BaseAdapter implements SpinnerAdapter { + private CursorAdapter inner; + private int mIndexUserId; + private int mIndexKeyId; + private int mIndexMasterKeyId; + + public SelectKeyAdapter() { + inner = new CursorAdapter(null, null, 0) { + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return View.inflate(getContext(), R.layout.keyspinner_key, null); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); + ((TextView) view.findViewById(android.R.id.title)).setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")")); + ((TextView) view.findViewById(android.R.id.text1)).setText(userId[1]); + ((TextView) view.findViewById(android.R.id.text2)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); + } + + @Override + public long getItemId(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(mIndexMasterKeyId); + } + }; + } + + public Cursor swapCursor(Cursor newCursor) { + if (newCursor == null) return inner.swapCursor(null); + + mIndexKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.KEY_ID); + mIndexUserId = newCursor.getColumnIndex(KeychainContract.KeyRings.USER_ID); + mIndexMasterKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID); + if (newCursor.moveToFirst()) { + do { + if (newCursor.getLong(mIndexMasterKeyId) == mSelectedKeyId) { + setSelection(newCursor.getPosition() + 1); + } + } while (newCursor.moveToNext()); + } + return inner.swapCursor(newCursor); + } + + @Override + public int getCount() { + return inner.getCount() + 1; + } + + @Override + public Object getItem(int position) { + if (position == 0) return null; + return inner.getItem(position - 1); + } + + @Override + public long getItemId(int position) { + if (position == 0) return Constants.key.none; + return inner.getItemId(position - 1); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + try { + View v = getDropDownView(position, convertView, parent); + v.findViewById(android.R.id.text1).setVisibility(View.GONE); + return v; + } catch (NullPointerException e) { + // This is for the preview... + return View.inflate(getContext(), android.R.layout.simple_list_item_1, null); + } + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + View v; + if (position == 0) { + if (convertView == null) { + v = inner.newView(null, null, parent); + } else { + v = convertView; + } + ((TextView) v.findViewById(android.R.id.title)).setText("None"); + v.findViewById(android.R.id.text1).setVisibility(View.GONE); + v.findViewById(android.R.id.text2).setVisibility(View.GONE); + } else { + v = inner.getView(position - 1, convertView, parent); + v.findViewById(android.R.id.text1).setVisibility(View.VISIBLE); + v.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); + } + return v; + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java new file mode 100644 index 000000000..cbec7f920 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -0,0 +1,48 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.util.AttributeSet; +import org.sufficientlysecure.keychain.provider.KeychainContract; + +public class SignKeySpinner extends KeySpinner { + public SignKeySpinner(Context context) { + super(context); + } + + public SignKeySpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SignKeySpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public Loader onCreateLoader() { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri(); + + // These are the rows that we will retrieve. + String[] projection = new String[]{ + KeychainContract.KeyRings._ID, + KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.KEY_ID, + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.IS_EXPIRED, + KeychainContract.KeyRings.HAS_SIGN, + KeychainContract.KeyRings.HAS_ANY_SECRET + }; + + String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " + KeychainContract.KeyRings.HAS_SIGN + " NOT NULL AND " + + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getContext(), baseUri, projection, where, null, null); + } +} -- cgit v1.2.3 From 9fab740aadb76883105b61451c047fc1d4b27f1f Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 12:22:44 +0200 Subject: add HAS_CERTIFY (not sure why it's missing) --- .../keychain/provider/KeychainContract.java | 1 + .../keychain/provider/KeychainProvider.java | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index dd59f8603..c239ea7f7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -111,6 +111,7 @@ public class KeychainContract { public static final String HAS_ANY_SECRET = "has_any_secret"; public static final String HAS_ENCRYPT = "has_encrypt"; public static final String HAS_SIGN = "has_sign"; + public static final String HAS_CERTIFY = "has_certify"; public static final String PUBKEY_DATA = "pubkey_data"; public static final String PRIVKEY_DATA = "privkey_data"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index c914cb5b7..ed12fb94a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -271,6 +271,8 @@ public class KeychainProvider extends ContentProvider { "kE." + Keys.KEY_ID + " AS " + KeyRings.HAS_ENCRYPT); projectionMap.put(KeyRings.HAS_SIGN, "kS." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN); + projectionMap.put(KeyRings.HAS_CERTIFY, + "kC." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN); projectionMap.put(KeyRings.IS_EXPIRED, "(" + Tables.KEYS + "." + Keys.EXPIRY + " IS NOT NULL AND " + Tables.KEYS + "." + Keys.EXPIRY + " < " + new Date().getTime() / 1000 + ") AS " + KeyRings.IS_EXPIRED); @@ -324,6 +326,15 @@ public class KeychainProvider extends ContentProvider { + " AND ( kS." + Keys.EXPIRY + " IS NULL OR kS." + Keys.EXPIRY + " >= " + new Date().getTime() / 1000 + " )" + ")" : "") + + (plist.contains(KeyRings.HAS_CERTIFY) ? + " LEFT JOIN " + Tables.KEYS + " AS kC ON (" + +"kC." + Keys.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND kC." + Keys.IS_REVOKED + " = 0" + + " AND kC." + Keys.CAN_CERTIFY + " = 1" + + " AND ( kC." + Keys.EXPIRY + " IS NULL OR kC." + Keys.EXPIRY + + " >= " + new Date().getTime() / 1000 + " )" + + ")" : "") ); qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0"); // in case there are multiple verifying certificates -- cgit v1.2.3 From 07d6a26778b69c5340f5bbf11dcab970c63783d4 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 15:23:12 +0200 Subject: add OnKeyChangedListener to KeySpinner --- .../keychain/ui/EncryptAsymmetricFragment.java | 11 ++---- .../keychain/ui/widget/KeySpinner.java | 41 ++++++++++++++++++++-- 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 41566cffc..748cbca14 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -101,15 +101,10 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); mSign = (KeySpinner) view.findViewById(R.id.sign); - mSign.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + mSign.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - setSignatureKeyId(parent.getAdapter().getItemId(position)); - } - - @Override - public void onNothingSelected(AdapterView parent) { - setSignatureKeyId(Constants.key.none); + public void onKeyChanged(long masterKeyId) { + setSignatureKeyId(masterKeyId); } }); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index b8d83311a..fe3c61197 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -10,6 +10,7 @@ import android.support.v4.widget.CursorAdapter; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Spinner; import android.widget.SpinnerAdapter; @@ -23,27 +24,62 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; public abstract class KeySpinner extends Spinner { + public interface OnKeyChangedListener { + public void onKeyChanged(long masterKeyId); + } + private long mSelectedKeyId; private SelectKeyAdapter mAdapter = new SelectKeyAdapter(); + private OnKeyChangedListener mListener; public KeySpinner(Context context) { super(context); + initView(); } public KeySpinner(Context context, AttributeSet attrs) { super(context, attrs); + initView(); } public KeySpinner(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + initView(); + } + + private void initView() { + setAdapter(mAdapter); + super.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (mListener != null) { + mListener.onKeyChanged(id); + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + if (mListener != null) { + mListener.onKeyChanged(Constants.key.none); + } + } + }); } public abstract Loader onCreateLoader(); + @Override + public void setOnItemSelectedListener(OnItemSelectedListener listener) { + throw new UnsupportedOperationException(); + } + + public void setOnKeyChangedListener(OnKeyChangedListener listener) { + mListener = listener; + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - setAdapter(mAdapter); if (getContext() instanceof FragmentActivity) { ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(hashCode(), null, new LoaderManager.LoaderCallbacks() { @Override @@ -97,8 +133,7 @@ public abstract class KeySpinner extends Spinner { @Override public long getItemId(int position) { - mCursor.moveToPosition(position); - return mCursor.getLong(mIndexMasterKeyId); + return ((Cursor) getItem(position)).getLong(mIndexMasterKeyId); } }; } -- cgit v1.2.3 From 00286744f232bec569b46411db7be62e40c534d0 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 15:44:54 +0200 Subject: small bug in has_certify --- .../java/org/sufficientlysecure/keychain/provider/KeychainProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index ed12fb94a..2c552a060 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -272,7 +272,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.HAS_SIGN, "kS." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN); projectionMap.put(KeyRings.HAS_CERTIFY, - "kC." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN); + "kC." + Keys.KEY_ID + " AS " + KeyRings.HAS_CERTIFY); projectionMap.put(KeyRings.IS_EXPIRED, "(" + Tables.KEYS + "." + Keys.EXPIRY + " IS NOT NULL AND " + Tables.KEYS + "." + Keys.EXPIRY + " < " + new Date().getTime() / 1000 + ") AS " + KeyRings.IS_EXPIRED); -- cgit v1.2.3 From a6118877ff1b096925c908583985889d30087e24 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 16:00:07 +0200 Subject: Add and use CertifyKeySpinner --- .../keychain/ui/CertifyKeyActivity.java | 32 +++++++-------- .../keychain/ui/widget/CertifyKeySpinner.java | 48 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index c1986825c..d1e8a80dc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -34,6 +34,7 @@ import android.support.v7.app.ActionBarActivity; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -56,6 +57,8 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner; +import org.sufficientlysecure.keychain.ui.widget.KeySpinner; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -64,18 +67,17 @@ import java.util.ArrayList; /** * Signs the specified public key with the specified secret master key */ -public class CertifyKeyActivity extends ActionBarActivity implements - SelectSecretKeyLayoutFragment.SelectSecretKeyCallback, LoaderManager.LoaderCallbacks { +public class CertifyKeyActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks { private View mCertifyButton; private ImageView mActionCertifyImage; private CheckBox mUploadKeyCheckbox; private Spinner mSelectKeyserverSpinner; - private SelectSecretKeyLayoutFragment mSelectKeyFragment; + private CertifyKeySpinner mCertifyKeySpinner; private Uri mDataUri; - private long mPubKeyId = 0; - private long mMasterKeyId = 0; + private long mPubKeyId = Constants.key.none; + private long mMasterKeyId = Constants.key.none; private ListView mUserIds; private UserIdsAdapter mUserIdsAdapter; @@ -89,8 +91,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements setContentView(R.layout.certify_key_activity); - mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getSupportFragmentManager() - .findFragmentById(R.id.sign_key_select_key_fragment); + mCertifyKeySpinner = (CertifyKeySpinner) findViewById(R.id.certify_key_spinner); mSelectKeyserverSpinner = (Spinner) findViewById(R.id.upload_key_keyserver); mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); mCertifyButton = findViewById(R.id.certify_key_certify_button); @@ -101,8 +102,12 @@ public class CertifyKeyActivity extends ActionBarActivity implements mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light), PorterDuff.Mode.SRC_IN); - mSelectKeyFragment.setCallback(this); - mSelectKeyFragment.setFilterCertify(true); + mCertifyKeySpinner.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() { + @Override + public void onKeyChanged(long masterKeyId) { + mMasterKeyId = masterKeyId; + } + }); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this) @@ -135,7 +140,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements public void onClick(View v) { if (mPubKeyId != 0) { if (mMasterKeyId == 0) { - mSelectKeyFragment.setError(getString(R.string.select_key_to_certify)); Notify.showNotify(CertifyKeyActivity.this, getString(R.string.select_key_to_certify), Notify.Style.ERROR); } else { @@ -367,14 +371,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements startService(intent); } - /** - * callback from select key fragment - */ - @Override - public void onKeySelected(long secretKeyId) { - mMasterKeyId = secretKeyId; - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java new file mode 100644 index 000000000..b686d108b --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -0,0 +1,48 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.util.AttributeSet; +import org.sufficientlysecure.keychain.provider.KeychainContract; + +public class CertifyKeySpinner extends KeySpinner { + public CertifyKeySpinner(Context context) { + super(context); + } + + public CertifyKeySpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CertifyKeySpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public Loader onCreateLoader() { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri(); + + // These are the rows that we will retrieve. + String[] projection = new String[]{ + KeychainContract.KeyRings._ID, + KeychainContract.KeyRings.MASTER_KEY_ID, + KeychainContract.KeyRings.KEY_ID, + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.IS_EXPIRED, + KeychainContract.KeyRings.HAS_CERTIFY, + KeychainContract.KeyRings.HAS_ANY_SECRET + }; + + String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " + KeychainContract.KeyRings.HAS_CERTIFY + " NOT NULL AND " + + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getContext(), baseUri, projection, where, null, null); + } +} -- cgit v1.2.3 From 9ad09a398251c8dab4d8ca19fbb9eac68ebcad3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 16:12:42 +0200 Subject: Automcomplete names and emails in keyserver tab --- .../keychain/helper/ContactHelper.java | 18 ++++++++++++++++++ .../keychain/ui/ImportKeysServerFragment.java | 18 ++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 8697e49f7..96e1b25af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -234,6 +234,24 @@ public class ContactHelper { return new ArrayList(mails); } + public static List getContactNames(Context context) { + ContentResolver resolver = context.getContentResolver(); + Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, + new String[]{ContactsContract.Contacts.DISPLAY_NAME}, + null, null, null); + if (cursor == null) return null; + + Set names = new HashSet(); + while (cursor.moveToNext()) { + String name = cursor.getString(0); + if (name != null) { + names.add(name); + } + } + cursor.close(); + return new ArrayList(names); + } + public static Uri dataUriFromContactUri(Context context, Uri contactUri) { Cursor contactMasterKey = context.getContentResolver().query(contactUri, new String[]{ContactsContract.Data.DATA2}, null, null, null, null); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java index d339bc132..88caebc32 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java @@ -29,15 +29,19 @@ import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.util.Log; +import java.util.List; + public class ImportKeysServerFragment extends Fragment { public static final String ARG_QUERY = "query"; public static final String ARG_KEYSERVER = "keyserver"; @@ -46,7 +50,7 @@ public class ImportKeysServerFragment extends Fragment { private ImportKeysActivity mImportActivity; private View mSearchButton; - private EditText mQueryEditText; + private AutoCompleteTextView mQueryEditText; private View mConfigButton; private View mConfigLayout; private Spinner mServerSpinner; @@ -75,7 +79,7 @@ public class ImportKeysServerFragment extends Fragment { View view = inflater.inflate(R.layout.import_keys_server_fragment, container, false); mSearchButton = view.findViewById(R.id.import_server_search); - mQueryEditText = (EditText) view.findViewById(R.id.import_server_query); + mQueryEditText = (AutoCompleteTextView) view.findViewById(R.id.import_server_query); mConfigButton = view.findViewById(R.id.import_server_config_button); mConfigLayout = view.findViewById(R.id.import_server_config); mServerSpinner = (Spinner) view.findViewById(R.id.import_server_spinner); @@ -93,6 +97,16 @@ public class ImportKeysServerFragment extends Fragment { mSearchButton.setEnabled(false); } + List namesAndEmails = ContactHelper.getContactNames(getActivity()); + namesAndEmails.addAll(ContactHelper.getContactMails(getActivity())); + mQueryEditText.setThreshold(3); + mQueryEditText.setAdapter( + new ArrayAdapter + (getActivity(), android.R.layout.simple_spinner_dropdown_item, + namesAndEmails + ) + ); + mSearchButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { -- cgit v1.2.3 From eebd480e8d36bd94227e6c5cd4ac51eef61585ee Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 16:14:16 +0200 Subject: Fix KeySpinner on cursor change --- .../java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index fe3c61197..380361fc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -133,7 +133,12 @@ public abstract class KeySpinner extends Spinner { @Override public long getItemId(int position) { - return ((Cursor) getItem(position)).getLong(mIndexMasterKeyId); + try { + return ((Cursor) getItem(position)).getLong(mIndexMasterKeyId); + } catch (Exception e) { + // This can happen on concurrent modification :( + return Constants.key.none; + } } }; } -- cgit v1.2.3 From a19784ed7e930055a6a1d0a537f2f4f1d3ea1f21 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 16:27:50 +0200 Subject: merge: check fingerprints on merge operation! (this needs a testcase!) --- .../java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 5c8a85de9..20e78d7fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -45,6 +45,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Arrays; import java.util.Comparator; import java.util.Date; import java.util.Iterator; @@ -692,7 +693,8 @@ public class UncachedKeyRing { long masterKeyId = other.getMasterKeyId(); - if (getMasterKeyId() != masterKeyId) { + if (getMasterKeyId() != masterKeyId + || Arrays.equals(getFingerprint(), other.getFingerprint())) { log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, indent); return null; } -- cgit v1.2.3 From 2c408f679c691a29814ef7d53de7130e3aa22dfc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 16:34:57 +0200 Subject: dem logix --- .../main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 20e78d7fa..83c244d52 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -694,7 +694,7 @@ public class UncachedKeyRing { long masterKeyId = other.getMasterKeyId(); if (getMasterKeyId() != masterKeyId - || Arrays.equals(getFingerprint(), other.getFingerprint())) { + || !Arrays.equals(getFingerprint(), other.getFingerprint())) { log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, indent); return null; } -- cgit v1.2.3 From 9c0388939076c0d15de01941a41ab8428df5c668 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 17:10:08 +0200 Subject: tests: add ProviderHelperSaveTest, with long key id collision test --- .../org/sufficientlysecure/keychain/provider/KeychainDatabase.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 3a859f505..a90c88c3e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -349,4 +349,9 @@ public class KeychainDatabase extends SQLiteOpenHelper { copy(in, out); } + // for test cases ONLY!! + public void clearDatabase() { + getWritableDatabase().execSQL("delete from " + Tables.KEY_RINGS_PUBLIC); + } + } -- cgit v1.2.3 From 9af301ec7750e33f687de3e3cdbfceae5551451c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 17:12:17 +0200 Subject: handle modify and save errors in KeychainIntentResult --- .../keychain/provider/ProviderHelper.java | 4 +++ .../keychain/service/KeychainIntentService.java | 30 ++++++++++++++++------ .../keychain/ui/EditKeyFragment.java | 15 +++++------ 3 files changed, 33 insertions(+), 16 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index a13bb9c98..960c508f8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -86,6 +86,10 @@ public class ProviderHelper { this(context, new OperationLog(), 0); } + public ProviderHelper(Context context, OperationLog log) { + this(context, log, 0); + } + public ProviderHelper(Context context, OperationLog log, int indent) { mContext = context; mContentResolver = context.getContentResolver(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d6c470e11..0fdc62633 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; +import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -391,23 +392,36 @@ public class KeychainIntentService extends IntentService } /* Operation */ - ProviderHelper providerHelper = new ProviderHelper(this); PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 60, 100)); - EditKeyResult result; + EditKeyResult modifyResult; if (saveParcel.mMasterKeyId != null) { String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE); CanonicalizedSecretKeyRing secRing = - providerHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId); + new ProviderHelper(this).getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId); - result = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase); + modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase); } else { - result = keyOperations.createSecretKeyRing(saveParcel); + modifyResult = keyOperations.createSecretKeyRing(saveParcel); + } + + // If the edit operation didn't succeed, exit here + if ( ! modifyResult.success()) { + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, modifyResult); + return; } - UncachedKeyRing ring = result.getRing(); + UncachedKeyRing ring = modifyResult.getRing(); - providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); + // Save the keyring. The ProviderHelper is initialized with the previous log + SaveKeyringResult saveResult = new ProviderHelper(this, modifyResult.getLog()) + .saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); + + // If the edit operation didn't succeed, exit here + if ( ! saveResult.success()) { + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); + return; + } // cache new passphrase if (saveParcel.mNewPassphrase != null) { @@ -418,7 +432,7 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); /* Output */ - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); } catch (Exception e) { sendErrorToHandler(e); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 03074bb6a..b18d1626a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -48,8 +48,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.OperationResults; -import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; @@ -408,9 +407,9 @@ public class EditKeyFragment extends LoaderFragment implements public void handleMessage(Message message) { switch (message.what) { case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: - Long expiry = (Long) message.getData(). - getSerializable(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); - mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry; + mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = + (Long) message.getData().getSerializable( + EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); break; } getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); @@ -520,8 +519,8 @@ public class EditKeyFragment extends LoaderFragment implements if (returnData == null) { return; } - final OperationResults.EditKeyResult result = - returnData.getParcelable(EditKeyResult.EXTRA_RESULT); + final OperationResultParcel result = + returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); if (result == null) { return; } @@ -534,7 +533,7 @@ public class EditKeyFragment extends LoaderFragment implements // if good -> finish, return result to showkey and display there! Intent intent = new Intent(); - intent.putExtra(EditKeyResult.EXTRA_RESULT, result); + intent.putExtra(OperationResultParcel.EXTRA_RESULT, result); getActivity().setResult(EditKeyActivity.RESULT_OK, intent); getActivity().finish(); -- cgit v1.2.3 From e1958009bd022021971c1fd2f81557fb4fe99e4e Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 14 Aug 2014 18:10:22 +0200 Subject: Do not allow self certifying --- .../keychain/ui/CertifyKeyActivity.java | 2 +- .../keychain/ui/widget/CertifyKeySpinner.java | 16 ++++++++++++++-- .../keychain/ui/widget/KeySpinner.java | 6 +++++- 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index d1e8a80dc..7c6e94d5e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -34,7 +34,6 @@ import android.support.v7.app.ActionBarActivity; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -203,6 +202,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag if (data.moveToFirst()) { // TODO: put findViewById in onCreate! mPubKeyId = data.getLong(INDEX_MASTER_KEY_ID); + mCertifyKeySpinner.setHiddenMasterKeyId(mPubKeyId); String keyIdStr = PgpKeyHelper.convertKeyIdToHex(mPubKeyId); ((TextView) findViewById(R.id.key_id)).setText(keyIdStr); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index b686d108b..030a76136 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -6,9 +6,13 @@ import android.net.Uri; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.AttributeSet; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainDatabase; public class CertifyKeySpinner extends KeySpinner { + private long mHiddenMasterKeyId = Constants.key.none; + public CertifyKeySpinner(Context context) { super(context); } @@ -21,6 +25,11 @@ public class CertifyKeySpinner extends KeySpinner { super(context, attrs, defStyle); } + public void setHiddenMasterKeyId(long hiddenMasterKeyId) { + this.mHiddenMasterKeyId = hiddenMasterKeyId; + reload(); + } + @Override public Loader onCreateLoader() { // This is called when a new Loader needs to be created. This @@ -38,8 +47,11 @@ public class CertifyKeySpinner extends KeySpinner { KeychainContract.KeyRings.HAS_ANY_SECRET }; - String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " + KeychainContract.KeyRings.HAS_CERTIFY + " NOT NULL AND " - + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; + String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " + + KeychainContract.KeyRings.HAS_CERTIFY + " NOT NULL AND " + + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + + KeychainContract.KeyRings.IS_EXPIRED + " = 0 AND " + KeychainDatabase.Tables.KEYS + "." + + KeychainContract.KeyRings.MASTER_KEY_ID + " != " + mHiddenMasterKeyId; // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index 380361fc0..b12029239 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -80,8 +80,12 @@ public abstract class KeySpinner extends Spinner { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + reload(); + } + + public void reload() { if (getContext() instanceof FragmentActivity) { - ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(hashCode(), null, new LoaderManager.LoaderCallbacks() { + ((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(hashCode(), null, new LoaderManager.LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { return KeySpinner.this.onCreateLoader(); -- cgit v1.2.3 From 65e76f6e4465324af59a305c87c745fbedcaac46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 18:51:35 +0200 Subject: hacky fix to prevent key list from scrolling to top when opening nav drawer --- .../keychain/ui/KeyListFragment.java | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 3c97b1128..e7b7d2efc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -330,12 +330,12 @@ public class KeyListFragment extends LoaderFragment * Show dialog to delete key * * @param masterKeyIds - * @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not + * @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void showDeleteKeyDialog(final ActionMode mode, long[] masterKeyIds, boolean hasSecret) { // Can only work on singular secret keys - if(hasSecret && masterKeyIds.length > 1) { + if (hasSecret && masterKeyIds.length > 1) { Notify.showNotify(getActivity(), R.string.secret_cannot_multiple, Notify.Style.ERROR); return; @@ -365,6 +365,7 @@ public class KeyListFragment extends LoaderFragment public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { // Get the searchview MenuItem searchItem = menu.findItem(R.id.menu_key_list_search); + mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem); // Execute this when searching @@ -383,7 +384,6 @@ public class KeyListFragment extends LoaderFragment @Override public boolean onMenuItemActionCollapse(MenuItem item) { mQuery = null; - mSearchView.setQuery("", true); getLoaderManager().restartLoader(0, null, KeyListFragment.this); return true; } @@ -399,11 +399,18 @@ public class KeyListFragment extends LoaderFragment @Override public boolean onQueryTextChange(String s) { + Log.d(Constants.TAG, "onQueryTextChange s:" + s); // Called when the action bar search text has changed. Update // the search filter, and restart the loader to do a new query // with this filter. - mQuery = !TextUtils.isEmpty(s) ? s : null; - getLoaderManager().restartLoader(0, null, this); + // If the nav drawer is opened, onQueryTextChange("") is executed. + // This hack prevents restarting the loader. + // TODO: better way to fix this? + String tmp = (mQuery == null) ? "" : mQuery; + if (!s.equals(tmp)) { + mQuery = s; + getLoaderManager().restartLoader(0, null, this); + } return true; } @@ -479,7 +486,7 @@ public class KeyListFragment extends LoaderFragment boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; boolean isExpired = !cursor.isNull(INDEX_EXPIRY) - && new Date(cursor.getLong(INDEX_EXPIRY)*1000).before(new Date()); + && new Date(cursor.getLong(INDEX_EXPIRY) * 1000).before(new Date()); boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; // Note: order is important! @@ -521,6 +528,7 @@ public class KeyListFragment extends LoaderFragment return mCursor.getInt(INDEX_HAS_ANY_SECRET) != 0; } + public long getMasterKeyId(int id) { if (!mCursor.moveToPosition(id)) { throw new IllegalStateException("couldn't move cursor to position " + id); @@ -625,7 +633,7 @@ public class KeyListFragment extends LoaderFragment public boolean isAnySecretSelected() { for (int pos : mSelection.keySet()) { - if(mAdapter.isSecretAvailable(pos)) + if (mAdapter.isSecretAvailable(pos)) return true; } return false; -- cgit v1.2.3 From 6e7b99940964e162d9b1134bc1607b8084bc2dcc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 18:56:08 +0200 Subject: fix subkey certification canonicalization (why did the test not catch this?!) --- .../main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 83c244d52..0a59ba9f8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -593,7 +593,7 @@ public class UncachedKeyRing { } // if we already have a cert, and this one is not newer: skip it - if (selfCert != null && selfCert.getCreationTime().before(cert.getCreationTime())) { + if (selfCert != null && cert.getCreationTime().before(selfCert.getCreationTime())) { log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB_DUP, indent); redundantCerts += 1; continue; -- cgit v1.2.3 From 48935557e89051fb905f20690522632f39b1406a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 19:12:29 +0200 Subject: support changing expiry of subkeys to none --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index bb692555e..fe84b3802 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -543,7 +543,8 @@ public class PgpKeyOperation { PGPPublicKey pKey = sKey.getPublicKey(); // expiry must not be in the past - if (change.mExpiry != null && new Date(change.mExpiry*1000).before(new Date())) { + if (change.mExpiry != null && change.mExpiry != 0 && + new Date(change.mExpiry*1000).before(new Date())) { log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY, indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); -- cgit v1.2.3 From 0f60bcbc3d2438a8822e9bc1c6d80f8d0b743e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 14 Aug 2014 19:25:39 +0200 Subject: Pass through of master key id in SaveKeyringResult --- .../keychain/provider/ProviderHelper.java | 38 +++++++++++----------- .../keychain/service/OperationResults.java | 37 ++++++++++++++++++--- .../keychain/ui/CreateKeyFinalFragment.java | 4 +-- 3 files changed, 54 insertions(+), 25 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 960c508f8..ac6ea015a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -648,7 +648,7 @@ public class ProviderHelper { if (publicRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } CanonicalizedPublicKeyRing canPublicRing; @@ -662,20 +662,20 @@ public class ProviderHelper { // If this is null, there is an error in the log so we can just return if (publicRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } // Canonicalize this keyring, to assert a number of assumptions made about it. canPublicRing = (CanonicalizedPublicKeyRing) publicRing.canonicalize(mLog, mIndent); if (canPublicRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } // Early breakout if nothing changed if (Arrays.hashCode(publicRing.getEncoded()) == Arrays.hashCode(oldPublicRing.getEncoded())) { log(LogLevel.OK, LogType.MSG_IP_SUCCESS_IDENTICAL); - return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog); + return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog, null); } } catch (NotFoundException e) { // Not an issue, just means we are dealing with a new keyring. @@ -683,7 +683,7 @@ public class ProviderHelper { // Canonicalize this keyring, to assert a number of assumptions made about it. canPublicRing = (CanonicalizedPublicKeyRing) publicRing.canonicalize(mLog, mIndent); if (canPublicRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } } @@ -696,12 +696,12 @@ public class ProviderHelper { // Merge data from new public ring into secret one secretRing = secretRing.merge(publicRing, mLog, mIndent); if (secretRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } // This has always been a secret key ring, this is a safe cast canSecretRing = (CanonicalizedSecretKeyRing) secretRing.canonicalize(mLog, mIndent); if (canSecretRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } } catch (NotFoundException e) { @@ -720,11 +720,11 @@ public class ProviderHelper { } } - return new SaveKeyringResult(result, mLog); + return new SaveKeyringResult(result, mLog, canSecretRing); } catch (IOException e) { log(LogLevel.ERROR, LogType.MSG_IP_FAIL_IO_EXC); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } finally { mIndent -= 1; } @@ -740,7 +740,7 @@ public class ProviderHelper { if ( ! secretRing.isSecret()) { log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } CanonicalizedSecretKeyRing canSecretRing; @@ -754,14 +754,14 @@ public class ProviderHelper { // If this is null, there is an error in the log so we can just return if (secretRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } // Canonicalize this keyring, to assert a number of assumptions made about it. // This is a safe cast, because we made sure this is a secret ring above canSecretRing = (CanonicalizedSecretKeyRing) secretRing.canonicalize(mLog, mIndent); if (canSecretRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } // Early breakout if nothing changed @@ -769,7 +769,7 @@ public class ProviderHelper { == Arrays.hashCode(oldSecretRing.getEncoded())) { log(LogLevel.OK, LogType.MSG_IS_SUCCESS_IDENTICAL, PgpKeyHelper.convertKeyIdToHex(masterKeyId) ); - return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog); + return new SaveKeyringResult(SaveKeyringResult.UPDATED, mLog, null); } } catch (NotFoundException e) { // Not an issue, just means we are dealing with a new keyring @@ -778,7 +778,7 @@ public class ProviderHelper { // This is a safe cast, because we made sure this is a secret ring above canSecretRing = (CanonicalizedSecretKeyRing) secretRing.canonicalize(mLog, mIndent); if (canSecretRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } } @@ -791,7 +791,7 @@ public class ProviderHelper { // Merge data from new secret ring into public one publicRing = oldPublicRing.merge(secretRing, mLog, mIndent); if (publicRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } } catch (NotFoundException e) { @@ -801,24 +801,24 @@ public class ProviderHelper { CanonicalizedPublicKeyRing canPublicRing = (CanonicalizedPublicKeyRing) publicRing.canonicalize(mLog, mIndent); if (canPublicRing == null) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } int result; result = saveCanonicalizedPublicKeyRing(canPublicRing, progress, true); if ((result & SaveKeyringResult.RESULT_ERROR) == SaveKeyringResult.RESULT_ERROR) { - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } progress.setProgress(LogType.MSG_IP_REINSERT_SECRET.getMsgId(), 90, 100); result = saveCanonicalizedSecretKeyRing(canSecretRing); - return new SaveKeyringResult(result, mLog); + return new SaveKeyringResult(result, mLog, canSecretRing); } catch (IOException e) { log(LogLevel.ERROR, LogType.MSG_IS_FAIL_IO_EXC); - return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog); + return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } finally { mIndent -= 1; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 543b83edb..d58392d77 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -29,6 +29,8 @@ import com.github.johnpersano.supertoasts.util.OnClickWrapper; import com.github.johnpersano.supertoasts.util.Style; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; @@ -49,18 +51,21 @@ public abstract class OperationResults { public static final int RESULT_WITH_WARNINGS = 16; // No keys to import... - public static final int RESULT_FAIL_NOTHING = 32 +1; + public static final int RESULT_FAIL_NOTHING = 32 + 1; public boolean isOkBoth() { return (mResult & (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED)) == (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED); } + public boolean isOkNew() { return (mResult & RESULT_OK_NEWKEYS) == RESULT_OK_NEWKEYS; } + public boolean isOkUpdated() { return (mResult & RESULT_OK_UPDATED) == RESULT_OK_UPDATED; } + public boolean isFailNothing() { return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING; } @@ -124,7 +129,7 @@ public abstract class OperationResults { if (this.isOkBoth()) { str = activity.getResources().getQuantityString( R.plurals.import_keys_added_and_updated_1, mNewKeys, mNewKeys); - str += " "+ activity.getResources().getQuantityString( + str += " " + activity.getResources().getQuantityString( R.plurals.import_keys_added_and_updated_2, mUpdatedKeys, mUpdatedKeys, withWarnings); } else if (isOkUpdated()) { str = activity.getResources().getQuantityString( @@ -188,7 +193,7 @@ public abstract class OperationResults { public final Long mRingMasterKeyId; public EditKeyResult(int result, OperationLog log, - UncachedKeyRing ring) { + UncachedKeyRing ring) { super(result, log); mRing = ring; mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null; @@ -224,8 +229,12 @@ public abstract class OperationResults { public static class SaveKeyringResult extends OperationResultParcel { - public SaveKeyringResult(int result, OperationLog log) { + public final Long mRingMasterKeyId; + + public SaveKeyringResult(int result, OperationLog log, + CanonicalizedKeyRing ring) { super(result, log); + mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null; } // Some old key was updated @@ -240,6 +249,26 @@ public abstract class OperationResults { return (mResult & UPDATED) == UPDATED; } + public SaveKeyringResult(Parcel source) { + super(source); + mRingMasterKeyId = source.readLong(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeLong(mRingMasterKeyId); + } + + public static Creator CREATOR = new Creator() { + public SaveKeyringResult createFromParcel(final Parcel source) { + return new SaveKeyringResult(source); + } + + public SaveKeyringResult[] newArray(final int size) { + return new SaveKeyringResult[size]; + } + }; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 773be816a..3fc9e7f31 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -140,7 +140,7 @@ public class CreateKeyFinalFragment extends Fragment { if (returnData == null) { return; } - final OperationResults.EditKeyResult result = + final OperationResults.SaveKeyringResult result = returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); if (result == null) { return; @@ -191,7 +191,7 @@ public class CreateKeyFinalFragment extends Fragment { getActivity().startService(intent); } - private void uploadKey(final OperationResults.EditKeyResult editKeyResult) { + private void uploadKey(final OperationResults.SaveKeyringResult editKeyResult) { // Send all information needed to service to upload key in other thread final Intent intent = new Intent(getActivity(), KeychainIntentService.class); -- cgit v1.2.3 From 09d37a5fa6b431bd7be91aca9a7bbae5af928453 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 14 Aug 2014 22:12:07 +0200 Subject: fix keys with no expiry in ui code --- .../sufficientlysecure/keychain/service/OperationResults.java | 9 +++++++-- .../sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java | 2 +- .../keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index d58392d77..1c83873be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -205,13 +205,18 @@ public abstract class OperationResults { public EditKeyResult(Parcel source) { super(source); - mRingMasterKeyId = source.readLong(); + mRingMasterKeyId = source.readInt() != 0 ? source.readLong() : null; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); - dest.writeLong(mRingMasterKeyId); + if (mRingMasterKeyId == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + dest.writeLong(mRingMasterKeyId); + } } public static Creator CREATOR = new Creator() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index d457e75bd..6df84a056 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -183,7 +183,7 @@ public class SubkeysAdapter extends CursorAdapter { SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); if (subkeyChange != null) { - if (subkeyChange.mExpiry == null) { + if (subkeyChange.mExpiry == null || subkeyChange.mExpiry == 0L) { expiryDate = null; } else { expiryDate = new Date(subkeyChange.mExpiry * 1000); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index aa63f9944..276ad15fc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -141,7 +141,7 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { dismiss(); Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null); + data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, 0L); sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); } }); -- cgit v1.2.3 From cf450d24fbcbbd9bc56959e387bd52141004bde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 15 Aug 2014 10:19:46 +0200 Subject: Remove subkeys.pgp.net keyserver, often down and no hkps --- .../org/sufficientlysecure/keychain/Constants.java | 2 +- .../keychain/helper/Preferences.java | 27 ++++++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 755d74ac2..7cfc11bc6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -72,7 +72,7 @@ public final class Constants { public static final class Defaults { public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, subkeys.pgp.net, hkps://pgp.mit.edu"; - public static final int KEY_SERVERS_VERSION = 2; + public static final int KEY_SERVERS_VERSION = 3; } public static final class DrawerItems { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index 80b047530..14ae46840 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -26,6 +26,10 @@ import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.ListIterator; import java.util.Vector; /** @@ -175,15 +179,24 @@ public class Preferences { // migrate keyserver to hkps if (mSharedPreferences.getInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, 0) != Constants.Defaults.KEY_SERVERS_VERSION) { - String[] servers = getKeyServers(); - for (int i = 0; i < servers.length; i++) { - if (servers[i].equals("pool.sks-keyservers.net")) { - servers[i] = "hkps://hkps.pool.sks-keyservers.net"; - } else if (servers[i].equals("pgp.mit.edu")) { - servers[i] = "hkps://pgp.mit.edu"; + String[] serversArray = getKeyServers(); + ArrayList servers = new ArrayList(Arrays.asList(serversArray)); + ListIterator it = servers.listIterator(); + while (it.hasNext()) { + String server = it.next(); + if (server.equals("pool.sks-keyservers.net")) { + // use HKPS! + it.set("hkps://hkps.pool.sks-keyservers.net"); + } else if (server.equals("pgp.mit.edu")) { + // use HKPS! + it.set("hkps://pgp.mit.edu"); + } else if (server.equals("subkeys.pgp.net")) { + // remove, because often down and no HKPS! + it.remove(); } + } - setKeyServers(servers); + setKeyServers(servers.toArray(new String[servers.size()])); mSharedPreferences.edit() .putInt(Constants.Pref.KEY_SERVERS_DEFAULT_VERSION, Constants.Defaults.KEY_SERVERS_VERSION) .commit(); -- cgit v1.2.3 From b1fa5d992268642adf8e860812027aa0a24f3617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 15 Aug 2014 11:00:45 +0200 Subject: Remove subkeys.pgp.net keyserver from defaults --- .../src/main/java/org/sufficientlysecure/keychain/Constants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 7cfc11bc6..bce093427 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -71,7 +71,7 @@ public final class Constants { } public static final class Defaults { - public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, subkeys.pgp.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 KEY_SERVERS_VERSION = 3; } -- cgit v1.2.3 From b1dc6639300c7ecafea2ac8f26d624e0275aa780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 15 Aug 2014 11:07:21 +0200 Subject: Remove old_apg --- .../sufficientlysecure/keychain/provider/KeychainDatabase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index a90c88c3e..1536c21fc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -227,7 +227,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { if (db.equals("apg.db")) { hasApgDb = true; } else if (db.equals("apg_old.db")) { - Log.d(Constants.TAG, "Found apg_old.db"); + Log.d(Constants.TAG, "Found apg_old.db, delete it!"); + context.getDatabasePath("apg_old.db").delete(); } } } @@ -310,9 +311,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { } } - // Move to a different file (but don't delete, just to be safe) - Log.d(Constants.TAG, "All done - moving apg.db to apg_old.db"); - context.getDatabasePath("apg.db").renameTo(context.getDatabasePath("apg_old.db")); + // delete old database + context.getDatabasePath("apg.db").delete(); } private static void copy(File in, File out) throws IOException { -- cgit v1.2.3 From 8d60d9f1031c7a2ad4d1484291497c1dff197e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 03:59:58 +0200 Subject: Fix encrypt only --- .../keychain/pgp/PgpSignEncrypt.java | 20 ++++++------- .../keychain/remote/OpenPgpService.java | 11 ++----- .../keychain/service/KeychainIntentService.java | 34 ++++++++++++---------- .../keychain/service/PassphraseCacheService.java | 6 ++-- 4 files changed, 34 insertions(+), 37 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 263b0c5bb..1784ae063 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -68,7 +68,7 @@ public class PgpSignEncrypt { private long mSignatureMasterKeyId; private int mSignatureHashAlgorithm; private String mSignaturePassphrase; - private boolean mEncryptToSigner; + private long mAdditionalEncryptId; private boolean mCleartextInput; private String mOriginalFilename; @@ -98,7 +98,7 @@ public class PgpSignEncrypt { this.mSignatureMasterKeyId = builder.mSignatureMasterKeyId; this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm; this.mSignaturePassphrase = builder.mSignaturePassphrase; - this.mEncryptToSigner = builder.mEncryptToSigner; + this.mAdditionalEncryptId = builder.mAdditionalEncryptId; this.mCleartextInput = builder.mCleartextInput; this.mOriginalFilename = builder.mOriginalFilename; } @@ -120,7 +120,7 @@ public class PgpSignEncrypt { private long mSignatureMasterKeyId = Constants.key.none; private int mSignatureHashAlgorithm = 0; private String mSignaturePassphrase = null; - private boolean mEncryptToSigner = false; + private long mAdditionalEncryptId = Constants.key.none; private boolean mCleartextInput = false; private String mOriginalFilename = ""; @@ -166,7 +166,7 @@ public class PgpSignEncrypt { } public Builder setSignatureMasterKeyId(long signatureMasterKeyId) { - this.mSignatureMasterKeyId = signatureMasterKeyId; + mSignatureMasterKeyId = signatureMasterKeyId; return this; } @@ -183,11 +183,11 @@ public class PgpSignEncrypt { /** * Also encrypt with the signing keyring * - * @param encryptToSigner + * @param additionalEncryptId * @return */ - public Builder setEncryptToSigner(boolean encryptToSigner) { - mEncryptToSigner = encryptToSigner; + public Builder setAdditionalEncryptId(long additionalEncryptId) { + mAdditionalEncryptId = additionalEncryptId; return this; } @@ -256,10 +256,10 @@ public class PgpSignEncrypt { + "\nenableCompression:" + enableCompression + "\nenableAsciiArmorOutput:" + mEnableAsciiArmorOutput); - // add signature key id to encryption ids (self-encrypt) - if (enableEncryption && enableSignature && mEncryptToSigner) { + // add additional key id to encryption ids (mostly to do self-encryption) + if (enableEncryption && mAdditionalEncryptId != Constants.key.none) { mEncryptionMasterKeyIds = Arrays.copyOf(mEncryptionMasterKeyIds, mEncryptionMasterKeyIds.length + 1); - mEncryptionMasterKeyIds[mEncryptionMasterKeyIds.length - 1] = mSignatureMasterKeyId; + mEncryptionMasterKeyIds[mEncryptionMasterKeyIds.length - 1] = mAdditionalEncryptId; } ArmoredOutputStream armorOut = null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 3541dad98..93cc08081 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -29,7 +29,6 @@ import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.util.OpenPgpApi; -import org.spongycastle.util.Arrays; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; @@ -261,10 +260,6 @@ public class OpenPgpService extends RemoteService { return result; } - // add own key for encryption - keyIds = Arrays.copyOf(keyIds, keyIds.length + 1); - keyIds[keyIds.length - 1] = accSettings.getKeyId(); - // build InputData and write into OutputStream // Get Input- and OutputStream from ParcelFileDescriptor InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); @@ -281,7 +276,8 @@ public class OpenPgpService extends RemoteService { .setCompressionId(accSettings.getCompression()) .setSymmetricEncryptionAlgorithm(accSettings.getEncryptionAlgorithm()) .setEncryptionMasterKeyIds(keyIds) - .setOriginalFilename(originalFilename); + .setOriginalFilename(originalFilename) + .setAdditionalEncryptId(accSettings.getKeyId()); // add acc key for encryption if (sign) { String passphrase; @@ -300,9 +296,6 @@ public class OpenPgpService extends RemoteService { builder.setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) .setSignatureMasterKeyId(accSettings.getKeyId()) .setSignaturePassphrase(passphrase); - } else { - // encrypt only - builder.setSignatureMasterKeyId(Constants.key.none); } try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 0fdc62633..83ade9b9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -247,27 +247,31 @@ public class KeychainIntentService extends IntentService String originalFilename = getOriginalFilename(data); /* Operation */ - PgpSignEncrypt.Builder builder = - new PgpSignEncrypt.Builder( - new ProviderHelper(this), - inputData, outStream); - builder.setProgressable(this); - - builder.setEnableAsciiArmorOutput(useAsciiArmor) + PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( + new ProviderHelper(this), + inputData, outStream + ); + builder.setProgressable(this) + .setEnableAsciiArmorOutput(useAsciiArmor) .setVersionHeader(PgpHelper.getVersionForHeader(this)) .setCompressionId(compressionId) .setSymmetricEncryptionAlgorithm( Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) .setEncryptionMasterKeyIds(encryptionKeyIds) .setSymmetricPassphrase(symmetricPassphrase) - .setSignatureMasterKeyId(signatureKeyId) - .setEncryptToSigner(true) - .setSignatureHashAlgorithm( - Preferences.getPreferences(this).getDefaultHashAlgorithm()) - .setSignaturePassphrase( - PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)) .setOriginalFilename(originalFilename); + try { + builder.setSignatureMasterKeyId(signatureKeyId) + .setSignaturePassphrase( + PassphraseCacheService.getCachedPassphrase(this, signatureKeyId)) + .setSignatureHashAlgorithm( + Preferences.getPreferences(this).getDefaultHashAlgorithm()) + .setAdditionalEncryptId(signatureKeyId); + } catch (PassphraseCacheService.KeyNotFoundException e) { + // encrypt-only + } + // this assumes that the bytes are cleartext (valid for current implementation!) if (source == IO_BYTES) { builder.setCleartextInput(true); @@ -406,7 +410,7 @@ public class KeychainIntentService extends IntentService } // If the edit operation didn't succeed, exit here - if ( ! modifyResult.success()) { + if (!modifyResult.success()) { sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, modifyResult); return; } @@ -418,7 +422,7 @@ public class KeychainIntentService extends IntentService .saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); // If the edit operation didn't succeed, exit here - if ( ! saveResult.success()) { + if (!saveResult.success()) { sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); return; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index ae1b026a5..3707fdebf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -77,7 +77,7 @@ public class PassphraseCacheService extends Service { private static final int NOTIFICATION_ID = 1; private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1; - private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND = 2; + private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2; private BroadcastReceiver mIntentReceiver; @@ -169,7 +169,7 @@ public class PassphraseCacheService extends Service { switch (returnMessage.what) { case MSG_PASSPHRASE_CACHE_GET_OKAY: return returnMessage.getData().getString(EXTRA_PASSPHRASE); - case MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND: + case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND: throw new KeyNotFoundException(); default: throw new KeyNotFoundException("should not happen!"); @@ -313,7 +313,7 @@ public class PassphraseCacheService extends Service { msg.setData(bundle); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "PassphraseCacheService: Passphrase for unknown key was requested!"); - msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NO_FOUND; + msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND; } try { -- cgit v1.2.3 From 443170b876751739df7249f0c497fdec6f6f892f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 04:11:39 +0200 Subject: do not pre-select revoked or expired keys --- .../keychain/remote/OpenPgpService.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 93cc08081..93c71f5d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -53,11 +54,16 @@ import java.util.Set; public class OpenPgpService extends RemoteService { - static final String[] KEYRING_PROJECTION = - new String[]{ - KeyRings._ID, - KeyRings.MASTER_KEY_ID, - }; + static final String[] EMAIL_SEARCH_PROJECTION = new String[]{ + KeyRings._ID, + KeyRings.MASTER_KEY_ID, + KeyRings.IS_EXPIRED, + KeyRings.IS_REVOKED, + }; + + // do not pre-select revoked or expired keys + static final String EMAIL_SEARCH_WHERE = KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; /** * Search database for key ids based on emails. @@ -76,7 +82,7 @@ public class OpenPgpService extends RemoteService { for (String email : encryptionUserIds) { Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); - Cursor cursor = getContentResolver().query(uri, KEYRING_PROJECTION, null, null, null); + Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); try { if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); -- cgit v1.2.3 From bbe986743c9e6c2a22df95e0fbde0de2340bf467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 05:28:51 +0200 Subject: API: Allow ACTION_SIGN_AND_ENCRYPT with no key ids or user ids extras, fix pre-selection of key ids (no revoked or expired ones, also select duplicates), refactor text using spannables --- .../keychain/remote/OpenPgpService.java | 100 +++++++++++---------- .../keychain/remote/ui/RemoteServiceActivity.java | 56 ++++++++---- 2 files changed, 88 insertions(+), 68 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 93c71f5d0..e2d809d9e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -72,52 +72,61 @@ public class OpenPgpService extends RemoteService { * @return */ private Intent getKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { - // find key ids to given emails in database - ArrayList keyIds = new ArrayList(); - + boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0); boolean missingUserIdsCheck = false; boolean duplicateUserIdsCheck = false; + + ArrayList keyIds = new ArrayList(); ArrayList missingUserIds = new ArrayList(); ArrayList duplicateUserIds = new ArrayList(); - - for (String email : encryptionUserIds) { - Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); - Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); - try { - if (cursor != null && cursor.moveToFirst()) { - long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); - keyIds.add(id); - } else { - missingUserIdsCheck = true; - missingUserIds.add(email); - Log.d(Constants.TAG, "user id missing"); - } - if (cursor != null && cursor.moveToNext()) { - duplicateUserIdsCheck = true; - duplicateUserIds.add(email); - Log.d(Constants.TAG, "more than one user id with the same email"); - } - } finally { - if (cursor != null) { - cursor.close(); + if (!noUserIdsCheck) { + for (String email : encryptionUserIds) { + // try to find the key for this specific email + Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); + Cursor cursor = getContentResolver().query(uri, EMAIL_SEARCH_PROJECTION, EMAIL_SEARCH_WHERE, null, null); + try { + // result should be one entry containing the key id + if (cursor != null && cursor.moveToFirst()) { + long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); + keyIds.add(id); + } else { + missingUserIdsCheck = true; + missingUserIds.add(email); + Log.d(Constants.TAG, "user id missing"); + } + // another entry for this email -> too keys with the same email inside user id + if (cursor != null && cursor.moveToNext()) { + duplicateUserIdsCheck = true; + duplicateUserIds.add(email); + + // also pre-select + long id = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID)); + keyIds.add(id); + Log.d(Constants.TAG, "more than one user id with the same email"); + } + } finally { + if (cursor != null) { + cursor.close(); + } } } } - // convert to long[] + // convert ArrayList to long[] long[] keyIdsArray = new long[keyIds.size()]; for (int i = 0; i < keyIdsArray.length; i++) { keyIdsArray[i] = keyIds.get(i); } - // allow the user to verify pub key selection - if (missingUserIdsCheck || duplicateUserIdsCheck) { - // build PendingIntent + if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) { + // allow the user to verify pub key selection + Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS); intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); + intent.putExtra(RemoteServiceActivity.EXTRA_NO_USER_IDS_CHECK, noUserIdsCheck); intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); - intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, duplicateUserIds); + intent.putExtra(RemoteServiceActivity.EXTRA_DUPLICATE_USER_IDS, duplicateUserIds); intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, @@ -129,16 +138,18 @@ public class OpenPgpService extends RemoteService { result.putExtra(OpenPgpApi.RESULT_INTENT, pi); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); return result; - } + } else { + // everything was easy, we have exactly one key for every email - if (keyIdsArray.length == 0) { - return null; - } + if (keyIdsArray.length == 0) { + Log.e(Constants.TAG, "keyIdsArray.length == 0, should never happen!"); + } - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIdsArray); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); - return result; + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_KEY_IDS, keyIdsArray); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); + return result; + } } private Intent getPassphraseBundleIntent(Intent data, long keyId) { @@ -241,10 +252,9 @@ public class OpenPgpService extends RemoteService { originalFilename = ""; } - long[] keyIds; - if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) { - keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); - } else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) { + // first try to get key ids from non-ambiguous key id extra + long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); + if (keyIds == null) { // get key ids based on given user ids String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); // give params through to activity... @@ -256,14 +266,6 @@ public class OpenPgpService extends RemoteService { // if not success -> result contains a PendingIntent for user interaction return result; } - } else { - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_ERROR, - new OpenPgpError(OpenPgpError.GENERIC_ERROR, - "Missing parameter user_ids or key_ids!") - ); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); - return result; } // build InputData and write into OutputStream diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java index 48c76d561..4b27e115b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java @@ -18,11 +18,20 @@ package org.sufficientlysecure.keychain.remote.ui; import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBarActivity; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.SpannedString; +import android.text.TextUtils; +import android.text.style.BulletSpan; +import android.text.style.StyleSpan; import android.view.View; import android.widget.TextView; @@ -39,7 +48,6 @@ import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.security.Provider; import java.util.ArrayList; public class RemoteServiceActivity extends ActionBarActivity { @@ -68,7 +76,8 @@ public class RemoteServiceActivity extends ActionBarActivity { // select pub keys action public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids"; public static final String EXTRA_MISSING_USER_IDS = "missing_user_ids"; - public static final String EXTRA_DUBLICATE_USER_IDS = "dublicate_user_ids"; + public static final String EXTRA_DUPLICATE_USER_IDS = "dublicate_user_ids"; + public static final String EXTRA_NO_USER_IDS_CHECK = "no_user_ids"; // error message public static final String EXTRA_ERROR_MESSAGE = "error_message"; @@ -229,32 +238,41 @@ public class RemoteServiceActivity extends ActionBarActivity { } else if (ACTION_SELECT_PUB_KEYS.equals(action)) { long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); + boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true); ArrayList missingUserIds = intent .getStringArrayListExtra(EXTRA_MISSING_USER_IDS); ArrayList dublicateUserIds = intent - .getStringArrayListExtra(EXTRA_DUBLICATE_USER_IDS); + .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS); + + SpannableStringBuilder ssb = new SpannableStringBuilder(); + final SpannableString textIntro = new SpannableString( + noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids) + : getString(R.string.api_select_pub_keys_text) + ); + textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(textIntro); - // TODO: do this with spannable instead of HTML to prevent parsing failures with weird user ids - String text = "" + getString(R.string.api_select_pub_keys_text) + ""; - text += "

"; if (missingUserIds != null && missingUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_missing_text); - text += "
"; - text += "
    "; + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_missing_text)); + ssb.append("\n"); for (String userId : missingUserIds) { - text += "
  • " + userId + "
  • "; + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); } - text += "
"; - text += "
"; } if (dublicateUserIds != null && dublicateUserIds.size() > 0) { - text += getString(R.string.api_select_pub_keys_dublicates_text); - text += "
"; - text += "
    "; + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_dublicates_text)); + ssb.append("\n"); for (String userId : dublicateUserIds) { - text += "
  • " + userId + "
  • "; + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); } - text += "
"; } // Inflate a "Done"/"Cancel" custom action bar view @@ -284,8 +302,8 @@ public class RemoteServiceActivity extends ActionBarActivity { setContentView(R.layout.api_remote_select_pub_keys); // set text on view - HtmlTextView textView = (HtmlTextView) findViewById(R.id.api_select_pub_keys_text); - textView.setHtmlFromString(text, true); + TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text); + textView.setText(ssb, TextView.BufferType.SPANNABLE); /* Load select pub keys fragment */ // Check that the activity is using the layout version with -- cgit v1.2.3 From c54fe21f44f118c59874fe97b662b3faea6ebc48 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 05:13:09 +0200 Subject: modifySecretKey: err out on revocation of nonexistent user id --- .../org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 12 ++++++++++++ .../keychain/service/OperationResultParcel.java | 1 + 2 files changed, 13 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index fe84b3802..06d8dff69 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -403,6 +403,18 @@ public class PgpKeyOperation { progress(R.string.progress_modify_revokeuid, (i-1) * (100 / saveParcel.mRevokeUserIds.size())); String userId = saveParcel.mRevokeUserIds.get(i); log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent, userId); + // Make sure the user id exists (yes these are 10 LoC in Java!) + boolean exists = false; + for (String uid : new IterableIterator(modifiedPublicKey.getUserIDs())) { + if (userId.equals(uid)) { + exists = true; + break; + } + } + if (!exists) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NOEXIST_REVOKE, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } // a duplicate revocation will be removed during canonicalization, so no need to // take care of that here. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 25dac2139..4c93e2a91 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -359,6 +359,7 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), + MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), -- cgit v1.2.3 From 1fa77d57d2bb0e82291364a046ddce0e17fa393f Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 05:15:12 +0200 Subject: modifySecretKey: err out on "use previous" expiry date for (sub)key creation --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 8 +++++++- .../keychain/service/OperationResultParcel.java | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 06d8dff69..d7658efef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -218,6 +218,11 @@ public class PgpKeyOperation { return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } + if (add.mExpiry == null) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NULL_EXPIRY, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + if (add.mAlgorithm == PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT) { log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_MASTER_ELGAMAL, indent); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); @@ -638,7 +643,8 @@ public class PgpKeyOperation { ); PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize, log, indent); subProgressPop(); - if(keyPair == null) { + if (keyPair == null) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent +1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 4c93e2a91..01c7611ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -347,6 +347,7 @@ public class OperationResultParcel implements Parcelable { MSG_CR_ERROR_NO_MASTER (R.string.msg_cr_error_no_master), MSG_CR_ERROR_NO_USER_ID (R.string.msg_cr_error_no_user_id), MSG_CR_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), + MSG_CR_ERROR_NULL_EXPIRY(R.string.msg_cr_error_null_expiry), MSG_CR_ERROR_KEYSIZE_512 (R.string.msg_cr_error_keysize_512), MSG_CR_ERROR_UNKNOWN_ALGO (R.string.msg_cr_error_unknown_algo), MSG_CR_ERROR_INTERNAL_PGP (R.string.msg_cr_error_internal_pgp), @@ -360,6 +361,7 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), + MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry), MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), -- cgit v1.2.3 From a943bebfdf063700c01170ea264e342283e5d6b3 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 06:24:40 +0200 Subject: support for master key modifications, among other stuff --- .../keychain/pgp/PgpKeyOperation.java | 479 +++++++++++++-------- .../keychain/service/OperationResultParcel.java | 13 +- 2 files changed, 310 insertions(+), 182 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index d7658efef..710bd42c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -253,7 +253,7 @@ public class PgpKeyOperation { masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); subProgressPush(50, 100); - return internal(sKR, masterSecretKey, add.mFlags, saveParcel, "", log); + return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, "", log); } catch (PGPException e) { log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_INTERNAL_PGP, indent); @@ -319,14 +319,17 @@ public class PgpKeyOperation { // read masterKeyFlags, and use the same as before. // since this is the master key, this contains at least CERTIFY_OTHER - int masterKeyFlags = readKeyFlags(masterSecretKey.getPublicKey()) | KeyFlags.CERTIFY_OTHER; + PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); + int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; + long masterKeyExpiry = masterPublicKey.getValidSeconds() == 0L ? 0L : + masterPublicKey.getCreationTime().getTime() / 1000 + masterPublicKey.getValidSeconds(); - return internal(sKR, masterSecretKey, masterKeyFlags, saveParcel, passphrase, log); + return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, passphrase, log); } private EditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey, - int masterKeyFlags, + int masterKeyFlags, long masterKeyExpiry, SaveKeyringParcel saveParcel, String passphrase, OperationLog log) { @@ -351,189 +354,196 @@ public class PgpKeyOperation { } } - // work on master secret key try { - PGPPublicKey modifiedPublicKey = masterPublicKey; + { // work on master secret key - // 2a. Add certificates for new user ids - subProgressPush(15, 25); - for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) { + PGPPublicKey modifiedPublicKey = masterPublicKey; - progress(R.string.progress_modify_adduid, (i-1) * (100 / saveParcel.mAddUserIds.size())); - String userId = saveParcel.mAddUserIds.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent, userId); + // 2a. Add certificates for new user ids + subProgressPush(15, 25); + for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) { - if (userId.equals("")) { - log.add(LogLevel.ERROR, LogType.MSG_MF_UID_ERROR_EMPTY, indent+1); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } + progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.mAddUserIds.size())); + String userId = saveParcel.mAddUserIds.get(i); + log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent, userId); - // this operation supersedes all previous binding and revocation certificates, - // so remove those to retain assertions from canonicalization for later operations - @SuppressWarnings("unchecked") - Iterator it = modifiedPublicKey.getSignaturesForID(userId); - if (it != null) { - for (PGPSignature cert : new IterableIterator(it)) { - if (cert.getKeyID() != masterPublicKey.getKeyID()) { - // foreign certificate?! error error error - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION - || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION - || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION - || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION - || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { - modifiedPublicKey = PGPPublicKey.removeCertification( - modifiedPublicKey, userId, cert); + if (userId.equals("")) { + log.add(LogLevel.ERROR, LogType.MSG_MF_UID_ERROR_EMPTY, indent + 1); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + + // this operation supersedes all previous binding and revocation certificates, + // so remove those to retain assertions from canonicalization for later operations + @SuppressWarnings("unchecked") + Iterator it = modifiedPublicKey.getSignaturesForID(userId); + if (it != null) { + for (PGPSignature cert : new IterableIterator(it)) { + if (cert.getKeyID() != masterPublicKey.getKeyID()) { + // foreign certificate?! error error error + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION + || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION + || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION + || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION + || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, cert); + } } } - } - // if it's supposed to be primary, we can do that here as well - boolean isPrimary = saveParcel.mChangePrimaryUserId != null - && userId.equals(saveParcel.mChangePrimaryUserId); - // generate and add new certificate - PGPSignature cert = generateUserIdSignature(masterPrivateKey, - masterPublicKey, userId, isPrimary, masterKeyFlags); - modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert); - } - subProgressPop(); + // if it's supposed to be primary, we can do that here as well + boolean isPrimary = saveParcel.mChangePrimaryUserId != null + && userId.equals(saveParcel.mChangePrimaryUserId); + // generate and add new certificate + PGPSignature cert = generateUserIdSignature(masterPrivateKey, + masterPublicKey, userId, isPrimary, masterKeyFlags, masterKeyExpiry); + modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert); + } + subProgressPop(); - // 2b. Add revocations for revoked user ids - subProgressPush(25, 40); - for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) { - - progress(R.string.progress_modify_revokeuid, (i-1) * (100 / saveParcel.mRevokeUserIds.size())); - String userId = saveParcel.mRevokeUserIds.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent, userId); - // Make sure the user id exists (yes these are 10 LoC in Java!) - boolean exists = false; - for (String uid : new IterableIterator(modifiedPublicKey.getUserIDs())) { - if (userId.equals(uid)) { - exists = true; - break; + // 2b. Add revocations for revoked user ids + subProgressPush(25, 40); + for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) { + + progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / saveParcel.mRevokeUserIds.size())); + String userId = saveParcel.mRevokeUserIds.get(i); + log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent, userId); + + // Make sure the user id exists (yes these are 10 LoC in Java!) + boolean exists = false; + //noinspection unchecked + for (String uid : new IterableIterator(modifiedPublicKey.getUserIDs())) { + if (userId.equals(uid)) { + exists = true; + break; + } + } + if (!exists) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NOEXIST_REVOKE, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - } - if (!exists) { - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NOEXIST_REVOKE, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - // a duplicate revocation will be removed during canonicalization, so no need to - // take care of that here. - PGPSignature cert = generateRevocationSignature(masterPrivateKey, - masterPublicKey, userId); - modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert); - } - subProgressPop(); + // a duplicate revocation will be removed during canonicalization, so no need to + // take care of that here. + PGPSignature cert = generateRevocationSignature(masterPrivateKey, + masterPublicKey, userId); + modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert); + } + subProgressPop(); - // 3. If primary user id changed, generate new certificates for both old and new - if (saveParcel.mChangePrimaryUserId != null) { - progress(R.string.progress_modify_primaryuid, 40); + // 3. If primary user id changed, generate new certificates for both old and new + if (saveParcel.mChangePrimaryUserId != null) { + progress(R.string.progress_modify_primaryuid, 40); - // keep track if we actually changed one - boolean ok = false; - log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent); - indent += 1; + // keep track if we actually changed one + boolean ok = false; + log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent); + indent += 1; - // we work on the modifiedPublicKey here, to respect new or newly revoked uids - // noinspection unchecked - for (String userId : new IterableIterator(modifiedPublicKey.getUserIDs())) { - boolean isRevoked = false; - PGPSignature currentCert = null; + // we work on the modifiedPublicKey here, to respect new or newly revoked uids // noinspection unchecked - for (PGPSignature cert : new IterableIterator( - modifiedPublicKey.getSignaturesForID(userId))) { - if (cert.getKeyID() != masterPublicKey.getKeyID()) { - // foreign certificate?! error error error + for (String userId : new IterableIterator(modifiedPublicKey.getUserIDs())) { + boolean isRevoked = false; + PGPSignature currentCert = null; + // noinspection unchecked + for (PGPSignature cert : new IterableIterator( + modifiedPublicKey.getSignaturesForID(userId))) { + if (cert.getKeyID() != masterPublicKey.getKeyID()) { + // foreign certificate?! error error error + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + // we know from canonicalization that if there is any revocation here, it + // is valid and not superseded by a newer certification. + if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) { + isRevoked = true; + continue; + } + // we know from canonicalization that there is only one binding + // certification here, so we can just work with the first one. + if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || + cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || + cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || + cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { + currentCert = cert; + } + } + + if (currentCert == null) { + // no certificate found?! error error error log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - // we know from canonicalization that if there is any revocation here, it - // is valid and not superseded by a newer certification. - if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) { - isRevoked = true; + + // we definitely should not update certifications of revoked keys, so just leave it. + if (isRevoked) { + // revoked user ids cannot be primary! + if (userId.equals(saveParcel.mChangePrimaryUserId)) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } continue; } - // we know from canonicalization that there is only one binding - // certification here, so we can just work with the first one. - if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || - cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || - cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || - cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { - currentCert = cert; - } - } - if (currentCert == null) { - // no certificate found?! error error error - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - - // we definitely should not update certifications of revoked keys, so just leave it. - if (isRevoked) { - // revoked user ids cannot be primary! - if (userId.equals(saveParcel.mChangePrimaryUserId)) { - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + // if this is~ the/a primary user id + if (currentCert.getHashedSubPackets() != null + && currentCert.getHashedSubPackets().isPrimaryUserID()) { + // if it's the one we want, just leave it as is + if (userId.equals(saveParcel.mChangePrimaryUserId)) { + ok = true; + continue; + } + // otherwise, generate new non-primary certification + log.add(LogLevel.DEBUG, LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent); + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, currentCert); + PGPSignature newCert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, false, + masterKeyFlags, masterKeyExpiry); + modifiedPublicKey = PGPPublicKey.addCertification( + modifiedPublicKey, userId, newCert); + continue; } - continue; - } - // if this is~ the/a primary user id - if (currentCert.getHashedSubPackets() != null - && currentCert.getHashedSubPackets().isPrimaryUserID()) { - // if it's the one we want, just leave it as is + // if we are here, this is not currently a primary user id + + // if it should be if (userId.equals(saveParcel.mChangePrimaryUserId)) { + // add shiny new primary user id certificate + log.add(LogLevel.DEBUG, LogType.MSG_MF_PRIMARY_NEW, indent); + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, currentCert); + PGPSignature newCert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, true, + masterKeyFlags, masterKeyExpiry); + modifiedPublicKey = PGPPublicKey.addCertification( + modifiedPublicKey, userId, newCert); ok = true; - continue; } - // otherwise, generate new non-primary certification - log.add(LogLevel.DEBUG, LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent); - modifiedPublicKey = PGPPublicKey.removeCertification( - modifiedPublicKey, userId, currentCert); - PGPSignature newCert = generateUserIdSignature( - masterPrivateKey, masterPublicKey, userId, false, masterKeyFlags); - modifiedPublicKey = PGPPublicKey.addCertification( - modifiedPublicKey, userId, newCert); - continue; - } - // if we are here, this is not currently a primary user id - - // if it should be - if (userId.equals(saveParcel.mChangePrimaryUserId)) { - // add shiny new primary user id certificate - log.add(LogLevel.DEBUG, LogType.MSG_MF_PRIMARY_NEW, indent); - modifiedPublicKey = PGPPublicKey.removeCertification( - modifiedPublicKey, userId, currentCert); - PGPSignature newCert = generateUserIdSignature( - masterPrivateKey, masterPublicKey, userId, true, masterKeyFlags); - modifiedPublicKey = PGPPublicKey.addCertification( - modifiedPublicKey, userId, newCert); - ok = true; + // user id is not primary and is not supposed to be - nothing to do here. + } - // user id is not primary and is not supposed to be - nothing to do here. + indent -= 1; + if (!ok) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NOEXIST_PRIMARY, indent); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } } - indent -= 1; - - if (!ok) { - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NOEXIST_PRIMARY, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + // Update the secret key ring + if (modifiedPublicKey != masterPublicKey) { + masterSecretKey = PGPSecretKey.replacePublicKey(masterSecretKey, modifiedPublicKey); + masterPublicKey = modifiedPublicKey; + sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey); } - } - // Update the secret key ring - if (modifiedPublicKey != masterPublicKey) { - masterSecretKey = PGPSecretKey.replacePublicKey(masterSecretKey, modifiedPublicKey); - masterPublicKey = modifiedPublicKey; - sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey); } // 4a. For each subkey change, generate new subkey binding certificate @@ -545,28 +555,47 @@ public class PgpKeyOperation { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE, indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); - // TODO allow changes in master key? this implies generating new user id certs... - if (change.mKeyId == masterPublicKey.getKeyID()) { - Log.e(Constants.TAG, "changing the master key not supported"); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId); if (sKey == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING, indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - PGPPublicKey pKey = sKey.getPublicKey(); // expiry must not be in the past if (change.mExpiry != null && change.mExpiry != 0 && new Date(change.mExpiry*1000).before(new Date())) { - log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY, + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PAST_EXPIRY, indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } + // if this is the master key, update uid certificates instead + if (change.mKeyId == masterPublicKey.getKeyID()) { + int flags = change.mFlags == null ? masterKeyFlags : change.mFlags; + long expiry = change.mExpiry == null ? masterKeyExpiry : change.mExpiry; + + if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NO_CERTIFY, indent + 1); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + + PGPPublicKey pKey = + updateMasterCertificates(masterPrivateKey, masterPublicKey, + flags, expiry, indent, log); + if (pKey == null) { + // error log entry has already been added by updateMasterCertificates itself + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + masterSecretKey = PGPSecretKey.replacePublicKey(masterSecretKey, pKey); + masterPublicKey = pKey; + sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey); + continue; + } + + // otherwise, continue working on the public key + PGPPublicKey pKey = sKey.getPublicKey(); + // keep old flags, or replace with new ones int flags = change.mFlags == null ? readKeyFlags(pKey) : change.mFlags; long expiry; @@ -583,7 +612,7 @@ public class PgpKeyOperation { //noinspection unchecked for (PGPSignature sig : new IterableIterator(pKey.getSignatures())) { // special case: if there is a revocation, don't use expiry from before - if (change.mExpiry == null + if ( (change.mExpiry == null || change.mExpiry == 0L) && sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) { expiry = 0; } @@ -631,8 +660,13 @@ public class PgpKeyOperation { SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent); - if (add.mExpiry != null && new Date(add.mExpiry*1000).before(new Date())) { - log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY, indent +1); + if (add.mExpiry == null) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + + if (add.mExpiry > 0L && new Date(add.mExpiry*1000).before(new Date())) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PAST_EXPIRY, indent +1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -652,7 +686,7 @@ public class PgpKeyOperation { PGPPublicKey pKey = keyPair.getPublicKey(); PGPSignature cert = generateSubkeyBindingSignature( masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey, - add.mFlags, add.mExpiry == null ? 0 : add.mExpiry); + add.mFlags, add.mExpiry); pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert); PGPSecretKey sKey; { @@ -713,21 +747,104 @@ public class PgpKeyOperation { } + /** Update all (non-revoked) uid signatures with new flags and expiry time. */ + private static PGPPublicKey updateMasterCertificates( + PGPPrivateKey masterPrivateKey, PGPPublicKey masterPublicKey, + int flags, long expiry, int indent, OperationLog log) + throws PGPException, IOException, SignatureException { + + // keep track if we actually changed one + boolean ok = false; + log.add(LogLevel.DEBUG, LogType.MSG_MF_MASTER, indent); + indent += 1; + + PGPPublicKey modifiedPublicKey = masterPublicKey; + + // we work on the modifiedPublicKey here, to respect new or newly revoked uids + // noinspection unchecked + for (String userId : new IterableIterator(modifiedPublicKey.getUserIDs())) { + boolean isRevoked = false; + PGPSignature currentCert = null; + // noinspection unchecked + for (PGPSignature cert : new IterableIterator( + modifiedPublicKey.getSignaturesForID(userId))) { + if (cert.getKeyID() != masterPublicKey.getKeyID()) { + // foreign certificate?! error error error + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return null; + } + // we know from canonicalization that if there is any revocation here, it + // is valid and not superseded by a newer certification. + if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) { + isRevoked = true; + continue; + } + // we know from canonicalization that there is only one binding + // certification here, so we can just work with the first one. + if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || + cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || + cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || + cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { + currentCert = cert; + } + } + + if (currentCert == null) { + // no certificate found?! error error error + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return null; + } + + // we definitely should not update certifications of revoked keys, so just leave it. + if (isRevoked) { + continue; + } + + // add shiny new user id certificate + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, currentCert); + PGPSignature newCert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, true, flags, expiry); + modifiedPublicKey = PGPPublicKey.addCertification( + modifiedPublicKey, userId, newCert); + ok = true; + + } + + if (!ok) { + // might happen, theoretically, if there is a key with no uid.. + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return null; + } + + return modifiedPublicKey; + + } + private static PGPSignature generateUserIdSignature( - PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary, int flags) + PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary, + int flags, long expiry) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( pKey.getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); - PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); - subHashedPacketsGen.setSignatureCreationTime(false, new Date()); - subHashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); - subHashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); - subHashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); - subHashedPacketsGen.setPrimaryUserID(false, primary); - subHashedPacketsGen.setKeyFlags(false, flags); - sGen.setHashedSubpackets(subHashedPacketsGen.generate()); + + PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); + { + hashedPacketsGen.setSignatureCreationTime(false, new Date()); + hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); + hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); + hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); + hashedPacketsGen.setPrimaryUserID(false, primary); + hashedPacketsGen.setKeyFlags(false, flags); + if (expiry > 0) { + hashedPacketsGen.setKeyExpirationTime( + false, expiry - pKey.getCreationTime().getTime() / 1000); + } + } + + sGen.setHashedSubpackets(hashedPacketsGen.generate()); sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey); return sGen.generateCertification(userId, pKey); } @@ -784,14 +901,15 @@ public class PgpKeyOperation { throws IOException, PGPException, SignatureException { // date for signing - Date todayDate = new Date(); + Date creationTime = new Date(); + PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); // If this key can sign, we need a primary key binding signature if ((flags & KeyFlags.SIGN_DATA) > 0) { // cross-certify signing keys PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); - subHashedPacketsGen.setSignatureCreationTime(false, todayDate); + subHashedPacketsGen.setSignatureCreationTime(false, creationTime); PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( pKey.getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); @@ -805,13 +923,12 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator hashedPacketsGen; { hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setSignatureCreationTime(false, todayDate); + hashedPacketsGen.setSignatureCreationTime(false, creationTime); hashedPacketsGen.setKeyFlags(false, flags); - } - - if (expiry > 0) { - long creationTime = pKey.getCreationTime().getTime() / 1000; - hashedPacketsGen.setKeyExpirationTime(false, expiry - creationTime); + if (expiry > 0) { + hashedPacketsGen.setKeyExpirationTime(false, + expiry - pKey.getCreationTime().getTime() / 1000); + } } PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 01c7611ff..138283b81 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -359,12 +359,15 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint), MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), + MSG_MF_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry), + MSG_MF_ERROR_PAST_EXPIRY(R.string.msg_mf_error_past_expiry), MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), + MSG_MF_MASTER (R.string.msg_mf_master), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), MSG_MF_PRIMARY_REPLACE_OLD (R.string.msg_mf_primary_replace_old), MSG_MF_PRIMARY_NEW (R.string.msg_mf_primary_new), @@ -372,7 +375,6 @@ public class OperationResultParcel implements Parcelable { MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing), MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id), MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new), - MSG_MF_SUBKEY_PAST_EXPIRY (R.string.msg_mf_subkey_past_expiry), MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke), MSG_MF_SUCCESS (R.string.msg_mf_success), MSG_MF_UID_ADD (R.string.msg_mf_uid_add), @@ -436,6 +438,15 @@ public class OperationResultParcel implements Parcelable { mParcels.add(new OperationResultParcel.LogEntryParcel(level, type, indent, (Object[]) null)); } + public boolean containsType(LogType type) { + for(LogEntryParcel entry : new IterableIterator(mParcels.iterator())) { + if (entry.mType == type) { + return true; + } + } + return false; + } + public boolean containsWarnings() { for(LogEntryParcel entry : new IterableIterator(mParcels.iterator())) { if (entry.mLevel == LogLevel.WARN || entry.mLevel == LogLevel.ERROR) { -- cgit v1.2.3 From de0d95432e40b9ed436c3509364ba49d2e487723 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 06:40:03 +0200 Subject: typed expected failures and a couple minor things --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 6 +++--- .../sufficientlysecure/keychain/service/OperationResultParcel.java | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 710bd42c6..3fcabf636 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -557,7 +557,7 @@ public class PgpKeyOperation { PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId); if (sKey == null) { - log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING, + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_SUBKEY_MISSING, indent + 1, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -638,7 +638,7 @@ public class PgpKeyOperation { PGPSecretKey sKey = sKR.getSecretKey(revocation); if (sKey == null) { - log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING, + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_SUBKEY_MISSING, indent+1, PgpKeyHelper.convertKeyIdToHex(revocation)); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } @@ -813,7 +813,7 @@ public class PgpKeyOperation { if (!ok) { // might happen, theoretically, if there is a key with no uid.. - log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_MASTER_NONE, indent); return null; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 138283b81..8e7dcd4aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -359,20 +359,21 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint), MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), + MSG_MF_ERROR_MASTER_NONE(R.string.msg_mf_error_master_none), MSG_MF_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry), MSG_MF_ERROR_PAST_EXPIRY(R.string.msg_mf_error_past_expiry), - MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), + MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), + MSG_MF_ERROR_SUBKEY_MISSING(R.string.msg_mf_error_subkey_missing), MSG_MF_MASTER (R.string.msg_mf_master), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), MSG_MF_PRIMARY_REPLACE_OLD (R.string.msg_mf_primary_replace_old), MSG_MF_PRIMARY_NEW (R.string.msg_mf_primary_new), MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change), - MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing), MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id), MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new), MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke), -- cgit v1.2.3 From 6e84c728011cebe44c3b2ef6c6cacee64098c16a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 06:49:46 +0200 Subject: tests: more expected error types --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 3fcabf636..26ad69eb7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -728,8 +728,8 @@ public class PgpKeyOperation { sKR = PGPSecretKeyRing.copyWithNewPassword(sKR, keyDecryptor, keyEncryptorNew); } - // This one must only be thrown by } catch (IOException e) { + Log.e(Constants.TAG, "encountered IOException while modifying key", e); log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_ENCODE, indent+1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } catch (PGPException e) { @@ -737,6 +737,7 @@ public class PgpKeyOperation { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent+1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } catch (SignatureException e) { + Log.e(Constants.TAG, "encountered SignatureException while modifying key", e); log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_SIG, indent+1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } -- cgit v1.2.3 From 7c7ba217148d0560744fd417c4e76726df3ffec7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 07:06:07 +0200 Subject: tests: add test for master key revocation --- .../main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 0a59ba9f8..ababd39e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -271,13 +271,12 @@ public class UncachedKeyRing { for (PGPSignature zert : new IterableIterator(masterKey.getKeySignatures())) { int type = zert.getSignatureType(); - // Disregard certifications on user ids, we will deal with those later + // These should most definitely not be here... if (type == PGPSignature.NO_CERTIFICATION || type == PGPSignature.DEFAULT_CERTIFICATION || type == PGPSignature.CASUAL_CERTIFICATION || type == PGPSignature.POSITIVE_CERTIFICATION || type == PGPSignature.CERTIFICATION_REVOCATION) { - // These should not be here... log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TYPE_UID, indent); modified = PGPPublicKey.removeCertification(modified, zert); badCerts += 1; -- cgit v1.2.3 From 2497722b48561ac1031f7ed9c0cb0526f694b1b3 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 07:12:37 +0200 Subject: fix travis tests (more), minor comment edits --- .../java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index ababd39e0..90abf05f5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -217,8 +217,7 @@ public class UncachedKeyRing { aos.close(); } - /** "Canonicalizes" a public key, removing inconsistencies in the process. This variant can be - * applied to public keyrings only. + /** "Canonicalizes" a public key, removing inconsistencies in the process. * * More specifically: * - Remove all non-verifying self-certificates @@ -235,9 +234,9 @@ public class UncachedKeyRing { * - If the key is a secret key, remove all certificates by foreign keys * - If no valid user id remains, log an error and return null * - * This operation writes an OperationLog which can be used as part of a OperationResultParcel. + * This operation writes an OperationLog which can be used as part of an OperationResultParcel. * - * @return A canonicalized key, or null on fatal error + * @return A canonicalized key, or null on fatal error (log will include a message in this case) * */ @SuppressWarnings("ConstantConditions") -- cgit v1.2.3 From 188eeb79c9f2eb536d73efee09a3698750c87dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 12:13:30 +0200 Subject: Fix and simplify in OperationResultParcel --- .../keychain/service/OperationResults.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 1c83873be..1fc496082 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -28,6 +28,7 @@ import com.github.johnpersano.supertoasts.SuperToast; import com.github.johnpersano.supertoasts.util.OnClickWrapper; import com.github.johnpersano.supertoasts.util.Style; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; @@ -190,13 +191,13 @@ public abstract class OperationResults { public static class EditKeyResult extends OperationResultParcel { private transient UncachedKeyRing mRing; - public final Long mRingMasterKeyId; + public final long mRingMasterKeyId; public EditKeyResult(int result, OperationLog log, UncachedKeyRing ring) { super(result, log); mRing = ring; - mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null; + mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none; } public UncachedKeyRing getRing() { @@ -205,18 +206,13 @@ public abstract class OperationResults { public EditKeyResult(Parcel source) { super(source); - mRingMasterKeyId = source.readInt() != 0 ? source.readLong() : null; + mRingMasterKeyId = source.readLong(); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); - if (mRingMasterKeyId == null) { - dest.writeInt(0); - } else { - dest.writeInt(1); - dest.writeLong(mRingMasterKeyId); - } + dest.writeLong(mRingMasterKeyId); } public static Creator CREATOR = new Creator() { @@ -234,12 +230,12 @@ public abstract class OperationResults { public static class SaveKeyringResult extends OperationResultParcel { - public final Long mRingMasterKeyId; + public final long mRingMasterKeyId; public SaveKeyringResult(int result, OperationLog log, CanonicalizedKeyRing ring) { super(result, log); - mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : null; + mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none; } // Some old key was updated -- cgit v1.2.3 From 474fc50b80ae57e3434c2d748895eda28d2ef548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 12:24:46 +0200 Subject: Always return a SaveKeyringResult from saving --- .../sufficientlysecure/keychain/service/KeychainIntentService.java | 7 ++++++- .../org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 83ade9b9b..036251cd6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -411,7 +411,12 @@ public class KeychainIntentService extends IntentService // If the edit operation didn't succeed, exit here if (!modifyResult.success()) { - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, modifyResult); + // always return SaveKeyringResult, so create one out of the EditKeyResult + SaveKeyringResult saveResult = new SaveKeyringResult( + SaveKeyringResult.RESULT_ERROR, + modifyResult.getLog(), + null); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); return; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 3fc9e7f31..461d25928 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -125,10 +125,9 @@ public class CreateKeyFinalFragment extends Fragment { Intent intent = new Intent(getActivity(), KeychainIntentService.class); intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); - // Message is received after importing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( getActivity(), - getString(R.string.progress_importing), + getString(R.string.progress_building_key), ProgressDialog.STYLE_HORIZONTAL) { public void handleMessage(Message message) { // handle messages by standard KeychainIntentServiceHandler first @@ -211,7 +210,6 @@ public class CreateKeyFinalFragment extends Fragment { intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - // Message is received after uploading is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) { public void handleMessage(Message message) { -- cgit v1.2.3 From 4d698c896a69148fbae4cccf7528ed9974449482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 12:28:49 +0200 Subject: Fix expiry when adding subkeys --- .../org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java | 6 +++--- .../java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 1 - .../keychain/ui/dialog/AddSubkeyDialogFragment.java | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 461d25928..22c0f7767 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -168,9 +168,9 @@ public class CreateKeyFinalFragment extends Fragment { Bundle data = new Bundle(); SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.CERTIFY_OTHER, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.SIGN_DATA, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); String userId = KeyRing.createUserId(mName, mEmail, null); parcel.mAddUserIds.add(userId); parcel.mChangePrimaryUserId = userId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index b18d1626a..409953ad5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -503,7 +503,6 @@ public class EditKeyFragment extends LoaderFragment implements private void save(String passphrase) { Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString()); - // Message is received after importing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( getActivity(), getString(R.string.progress_saving), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index cb31978e9..2b8768596 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -183,9 +183,9 @@ public class AddSubkeyDialogFragment extends DialogFragment { flags |= KeyFlags.AUTHENTICATION; } - Long expiry; + long expiry; if (mNoExpiryCheckBox.isChecked()) { - expiry = null; + expiry = 0L; } else { Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); //noinspection ResourceType -- cgit v1.2.3 From c1f9c5e4b5378f6c98f96e85ae82137c93f5009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 13:30:13 +0200 Subject: Fix ElGamal key creation, SUBKEY_BINDING cert must use algo of master key --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 26ad69eb7..ccd83c334 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -933,7 +933,7 @@ public class PgpKeyOperation { } PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PGPUtil.SHA1) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey); -- cgit v1.2.3 From ccf58a92fa915f948709fffde17f834bb1a88cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 13:42:55 +0200 Subject: Fix flags UI in add subkey dialog --- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 2 +- .../ui/dialog/AddSubkeyDialogFragment.java | 47 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java index be2e17c63..7e0027ddc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -106,7 +106,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter choices = new ArrayList(); choices.add(new Choice(PublicKeyAlgorithmTags.DSA, getResources().getString( R.string.dsa))); - if (!willBeMasterKey) { + if (!mWillBeMasterKey) { choices.add(new Choice(PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, getResources().getString( R.string.elgamal))); } @@ -246,7 +248,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId()); + updateUiForAlgorithm(((Choice) parent.getSelectedItem()).getId()); setCustomKeyVisibility(); setOkButtonAvailability(alertDialog); @@ -348,7 +350,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { } } - private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId) { + private void updateUiForAlgorithm(int algorithmId) { final ArrayAdapter keySizeAdapter = (ArrayAdapter) mKeySizeSpinner.getAdapter(); final Object selectedItem = mKeySizeSpinner.getSelectedItem(); keySizeAdapter.clear(); @@ -356,14 +358,51 @@ public class AddSubkeyDialogFragment extends DialogFragment { case PublicKeyAlgorithmTags.RSA_GENERAL: replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); + // allowed flags: + mFlagSign.setEnabled(true); + mFlagEncrypt.setEnabled(true); + mFlagAuthenticate.setEnabled(true); + + if (mWillBeMasterKey) { + mFlagCertify.setEnabled(true); + + mFlagCertify.setChecked(true); + mFlagSign.setChecked(false); + mFlagEncrypt.setChecked(false); + } else { + mFlagCertify.setEnabled(false); + + mFlagCertify.setChecked(false); + mFlagSign.setChecked(true); + mFlagEncrypt.setChecked(true); + } + mFlagAuthenticate.setChecked(false); break; case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length + // allowed flags: + mFlagCertify.setChecked(false); + mFlagCertify.setEnabled(false); + mFlagSign.setChecked(false); + mFlagSign.setEnabled(false); + mFlagEncrypt.setChecked(true); + mFlagEncrypt.setEnabled(true); + mFlagAuthenticate.setChecked(false); + mFlagAuthenticate.setEnabled(false); break; case PublicKeyAlgorithmTags.DSA: replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); + // allowed flags: + mFlagCertify.setChecked(false); + mFlagCertify.setEnabled(false); + mFlagSign.setChecked(true); + mFlagSign.setEnabled(true); + mFlagEncrypt.setChecked(false); + mFlagEncrypt.setEnabled(false); + mFlagAuthenticate.setChecked(false); + mFlagAuthenticate.setEnabled(false); break; } keySizeAdapter.notifyDataSetChanged(); -- cgit v1.2.3 From f2069020029f138ae02a7a9f2697f5737f568268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 16 Aug 2014 16:17:46 +0200 Subject: Fixing date picker issues --- .../ui/dialog/AddSubkeyDialogFragment.java | 5 +- .../ui/dialog/EditSubkeyExpiryDialogFragment.java | 64 +++++++++++++++------- 2 files changed, 47 insertions(+), 22 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index c35afd4fe..56c004f97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -189,10 +189,13 @@ public class AddSubkeyDialogFragment extends DialogFragment { if (mNoExpiryCheckBox.isChecked()) { expiry = 0L; } else { - Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); //noinspection ResourceType selectedCal.set(mExpiryDatePicker.getYear(), mExpiryDatePicker.getMonth(), mExpiryDatePicker.getDayOfMonth()); + // date picker uses default time zone, we need to convert to UTC + selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); + expiry = selectedCal.getTime().getTime() / 1000; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index 276ad15fc..fde8a3477 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -48,7 +48,6 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; private Messenger mMessenger; - private Calendar mExpiryCal; private DatePicker mDatePicker; @@ -75,15 +74,17 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); mMessenger = getArguments().getParcelable(ARG_MESSENGER); - Date creationDate = new Date(getArguments().getLong(ARG_CREATION_DATE) * 1000); - Date expiryDate = new Date(getArguments().getLong(ARG_EXPIRY_DATE) * 1000); + long creationDate = getArguments().getLong(ARG_CREATION_DATE); + long expiryDate = getArguments().getLong(ARG_EXPIRY_DATE); Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(creationDate); - mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mExpiryCal.setTime(expiryDate); + creationCal.setTime(new Date(creationDate * 1000)); + final Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + expiryCal.setTime(new Date(expiryDate * 1000)); - Log.d(Constants.TAG, "onCreateDialog"); + // date picker works with default time zone, we need to convert from UTC to default timezone + creationCal.setTimeZone(TimeZone.getDefault()); + expiryCal.setTimeZone(TimeZone.getDefault()); // Explicitly not using DatePickerDialog here! // DatePickerDialog is difficult to customize and has many problems (see old git versions) @@ -97,15 +98,40 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { mDatePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker); + // set default date + if (expiryDate == 0L) { + // if key has no expiry, set it to creation date +1 day + + Calendar creationCalPlusOne = (Calendar) creationCal.clone(); + creationCalPlusOne.add(Calendar.DAY_OF_MONTH, 1); + mDatePicker.init( + creationCalPlusOne.get(Calendar.YEAR), + creationCalPlusOne.get(Calendar.MONTH), + creationCalPlusOne.get(Calendar.DAY_OF_MONTH), + null + ); + } else { + // set date picker to current expiry date +1 day + + Calendar expiryCalPlusOne = (Calendar) expiryCal.clone(); + expiryCalPlusOne.add(Calendar.DAY_OF_MONTH, 1); + mDatePicker.init( + expiryCalPlusOne.get(Calendar.YEAR), + expiryCalPlusOne.get(Calendar.MONTH), + expiryCalPlusOne.get(Calendar.DAY_OF_MONTH), + null + ); + } + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { // will crash with IllegalArgumentException if we set a min date - // that is not before expiry - if (creationCal.before(mExpiryCal)) { + // that is before creation date + if (expiryDate == 0L || creationCal.before(expiryCal)) { mDatePicker.setMinDate(creationCal.getTime().getTime() + DateUtils.DAY_IN_MILLIS); } else { - // when creation date isn't available - mDatePicker.setMinDate(mExpiryCal.getTime().getTime() + // set min to expiry date + mDatePicker.setMinDate(expiryCal.getTime().getTime() + DateUtils.DAY_IN_MILLIS); } } @@ -115,19 +141,15 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public void onClick(DialogInterface dialog, int id) { dismiss(); - Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); //noinspection ResourceType selectedCal.set(mDatePicker.getYear(), mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); + // date picker uses default time zone, we need to convert to UTC + selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); - if (mExpiryCal != null) { - long numDays = (selectedCal.getTimeInMillis() / 86400000) - - (mExpiryCal.getTimeInMillis() / 86400000); - if (numDays > 0) { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } else { + long numDays = (selectedCal.getTimeInMillis() / 86400000) + - (expiryCal.getTimeInMillis() / 86400000); + if (numDays > 0) { Bundle data = new Bundle(); data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); -- cgit v1.2.3 From 62b7d2d7d80f7ecfa17d6a8484fecae21f42a92d Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 19:30:32 +0200 Subject: fix small log format string mistake for adding subkeys closes #768 --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index ccd83c334..5da8c5f6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -658,7 +658,8 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent); + log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, add.mKeysize, + PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm) ); if (add.mExpiry == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1); -- cgit v1.2.3 From e38f6a2a46c5b246f2f6a60d497f85f95c10908a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 19:45:14 +0200 Subject: use correct algorithm for signatures (actually fix heterogeneous subkeys) --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 5da8c5f6a..222c47215 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -828,7 +828,7 @@ public class PgpKeyOperation { int flags, long expiry) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PGPUtil.SHA1) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); @@ -855,7 +855,7 @@ public class PgpKeyOperation { PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PGPUtil.SHA1) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -869,7 +869,7 @@ public class PgpKeyOperation { PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PGPUtil.SHA1) + masterPublicKey.getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -934,7 +934,7 @@ public class PgpKeyOperation { } PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) + masterPublicKey.getAlgorithm(), PGPUtil.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey); -- cgit v1.2.3 From c00343d516f1afc2d4e062d30eba07689fc3092a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 16 Aug 2014 21:04:43 +0200 Subject: modify*Key: improve handling of passphrase modification (add tests, too) --- .../keychain/pgp/PgpKeyOperation.java | 50 +++++++++++++++++++++- .../keychain/service/OperationResultParcel.java | 4 ++ 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 222c47215..cdd2eacc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -698,7 +698,7 @@ public class PgpKeyOperation { // Build key encrypter and decrypter based on passphrase PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( PGPEncryptedData.CAST5, sha1Calc) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, sha1Calc, false, keyEncryptor); @@ -716,6 +716,8 @@ public class PgpKeyOperation { if (saveParcel.mNewPassphrase != null) { progress(R.string.progress_modify_passphrase, 90); log.add(LogLevel.INFO, LogType.MSG_MF_PASSPHRASE, indent); + indent += 1; + PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build() .get(HashAlgorithmTags.SHA1); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( @@ -726,7 +728,51 @@ public class PgpKeyOperation { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( saveParcel.mNewPassphrase.toCharArray()); - sKR = PGPSecretKeyRing.copyWithNewPassword(sKR, keyDecryptor, keyEncryptorNew); + // noinspection unchecked + for (PGPSecretKey sKey : new IterableIterator(sKR.getSecretKeys())) { + log.add(LogLevel.DEBUG, LogType.MSG_MF_PASSPHRASE_KEY, indent, + PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); + + boolean ok = false; + + try { + // try to set new passphrase + sKey = PGPSecretKey.copyWithNewPassword(sKey, keyDecryptor, keyEncryptorNew); + ok = true; + } catch (PGPException e) { + + // if this is the master key, error! + if (sKey.getKeyID() == masterPublicKey.getKeyID()) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PASSPHRASE_MASTER, indent+1); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + + // being in here means decrypt failed, likely due to a bad passphrase try + // again with an empty passphrase, maybe we can salvage this + try { + log.add(LogLevel.DEBUG, LogType.MSG_MF_PASSPHRASE_EMPTY_RETRY, indent+1); + PBESecretKeyDecryptor emptyDecryptor = + new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); + sKey = PGPSecretKey.copyWithNewPassword(sKey, emptyDecryptor, keyEncryptorNew); + ok = true; + } catch (PGPException e2) { + // non-fatal but not ok, handled below + } + } + + if (!ok) { + // for a subkey, it's merely a warning + log.add(LogLevel.WARN, LogType.MSG_MF_PASSPHRASE_FAIL, indent+1, + PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); + continue; + } + + sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); + + } + + indent -= 1; } } catch (IOException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 8e7dcd4aa..26fe63550 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -364,6 +364,7 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_NOEXIST_PRIMARY (R.string.msg_mf_error_noexist_primary), MSG_MF_ERROR_NOEXIST_REVOKE (R.string.msg_mf_error_noexist_revoke), MSG_MF_ERROR_NULL_EXPIRY (R.string.msg_mf_error_null_expiry), + MSG_MF_ERROR_PASSPHRASE_MASTER(R.string.msg_mf_error_passphrase_master), MSG_MF_ERROR_PAST_EXPIRY(R.string.msg_mf_error_past_expiry), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), @@ -371,6 +372,9 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_SUBKEY_MISSING(R.string.msg_mf_error_subkey_missing), MSG_MF_MASTER (R.string.msg_mf_master), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), + MSG_MF_PASSPHRASE_KEY (R.string.msg_mf_passphrase_key), + MSG_MF_PASSPHRASE_EMPTY_RETRY (R.string.msg_mf_passphrase_empty_retry), + MSG_MF_PASSPHRASE_FAIL (R.string.msg_mf_passphrase_fail), MSG_MF_PRIMARY_REPLACE_OLD (R.string.msg_mf_primary_replace_old), MSG_MF_PRIMARY_NEW (R.string.msg_mf_primary_new), MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change), -- cgit v1.2.3 From aa625d4fbf8cf97de5a81675d55e4ac004ef5f11 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 Aug 2014 00:49:14 +0200 Subject: parametrize FileImportCache for filename --- .../keychain/service/KeychainIntentService.java | 2 +- .../sufficientlysecure/keychain/ui/ImportKeysActivity.java | 3 ++- .../org/sufficientlysecure/keychain/util/FileImportCache.java | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 036251cd6..0505a6339 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -477,7 +477,7 @@ public class KeychainIntentService extends IntentService } else { // get entries from cached file FileImportCache cache = - new FileImportCache(this); + new FileImportCache(this, "key_import.pcl"); entries = cache.readCacheIntoList(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 255290de3..7df180296 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -503,7 +503,8 @@ public class ImportKeysActivity extends ActionBarActivity { // to prevent Java Binder problems on heavy imports // read FileImportCache for more info. try { - FileImportCache cache = new FileImportCache(this); + FileImportCache cache = + new FileImportCache(this, "key_import.pcl"); cache.writeCache(selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java index 5a4bf5311..35833adc6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java @@ -46,10 +46,11 @@ public class FileImportCache { private Context mContext; - private static final String FILENAME = "key_import.pcl"; + private final String mFilename; - public FileImportCache(Context context) { - this.mContext = context; + public FileImportCache(Context context, String filename) { + mContext = context; + mFilename = filename; } public void writeCache(ArrayList selectedEntries) throws IOException { @@ -64,7 +65,7 @@ public class FileImportCache { throw new IOException("cache dir is null!"); } - File tempFile = new File(mContext.getCacheDir(), FILENAME); + File tempFile = new File(mContext.getCacheDir(), mFilename); DataOutputStream oos = new DataOutputStream(new FileOutputStream(tempFile)); @@ -98,7 +99,7 @@ public class FileImportCache { throw new IOException("cache dir is null!"); } - final File tempFile = new File(cacheDir, FILENAME); + final File tempFile = new File(cacheDir, mFilename); final DataInputStream ois = new DataInputStream(new FileInputStream(tempFile)); return new Iterator() { -- cgit v1.2.3 From 14290c3ce9a1cfcf2b45c47198ba44737bd5d996 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 17 Aug 2014 03:29:03 +0200 Subject: consolidate: working implementation, lacking ui --- .../keychain/pgp/PgpImportExport.java | 21 ++- .../keychain/provider/KeychainDatabase.java | 2 +- .../keychain/provider/ProviderHelper.java | 181 ++++++++++++++++++++- .../keychain/service/KeychainIntentService.java | 15 ++ .../keychain/service/OperationResultParcel.java | 9 + .../keychain/service/OperationResults.java | 8 + .../keychain/ui/KeyListActivity.java | 60 +++++++ 7 files changed, 281 insertions(+), 15 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index f14eacda2..fd37112a5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; +import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -43,6 +44,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; public class PgpImportExport { @@ -60,10 +62,14 @@ public class PgpImportExport { private ProviderHelper mProviderHelper; public PgpImportExport(Context context, Progressable progressable) { + this(context, new ProviderHelper(context), progressable); + } + + public PgpImportExport(Context context, ProviderHelper providerHelper, Progressable progressable) { super(); this.mContext = context; this.mProgressable = progressable; - this.mProviderHelper = new ProviderHelper(context); + this.mProviderHelper = providerHelper; } public PgpImportExport(Context context, @@ -124,11 +130,14 @@ public class PgpImportExport { /** Imports keys from given data. If keyIds is given only those are imported */ public ImportKeyResult importKeyRings(List entries) { + return importKeyRings(entries.iterator(), entries.size()); + } + public ImportKeyResult importKeyRings(Iterator entries, int num) { updateProgress(R.string.progress_importing, 0, 100); // If there aren't even any keys, do nothing here. - if (entries == null || entries.size() == 0) { + if (entries == null || !entries.hasNext()) { return new ImportKeyResult( ImportKeyResult.RESULT_FAIL_NOTHING, mProviderHelper.getLog(), 0, 0, 0); } @@ -136,8 +145,8 @@ public class PgpImportExport { int newKeys = 0, oldKeys = 0, badKeys = 0; int position = 0; - int progSteps = 100 / entries.size(); - for (ParcelableKeyRing entry : entries) { + double progSteps = 100.0 / num; + for (ParcelableKeyRing entry : new IterableIterator(entries)) { try { UncachedKeyRing key = UncachedKeyRing.decodeFromData(entry.getBytes()); @@ -157,10 +166,10 @@ public class PgpImportExport { SaveKeyringResult result; if (key.isSecret()) { result = mProviderHelper.saveSecretKeyRing(key, - new ProgressScaler(mProgressable, position, (position+1)*progSteps, 100)); + new ProgressScaler(mProgressable, (int)(position*progSteps), (int)((position+1)*progSteps), 100)); } else { result = mProviderHelper.savePublicKeyRing(key, - new ProgressScaler(mProgressable, position, (position+1)*progSteps, 100)); + new ProgressScaler(mProgressable, (int)(position*progSteps), (int)((position+1)*progSteps), 100)); } if (!result.success()) { badKeys += 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 1536c21fc..560eb9ef8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -349,7 +349,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { copy(in, out); } - // for test cases ONLY!! + // DANGEROUS public void clearDatabase() { getWritableDatabase().execSQL("delete from " + Tables.KEY_RINGS_PUBLIC); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index ac6ea015a..3594ded51 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -28,12 +28,14 @@ import android.os.RemoteException; import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.NullProgressable; import org.sufficientlysecure.keychain.pgp.PgpHelper; +import org.sufficientlysecure.keychain.pgp.PgpImportExport; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; @@ -51,9 +53,12 @@ import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; +import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; +import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -63,6 +68,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -97,14 +103,6 @@ public class ProviderHelper { mIndent = indent; } - public void resetLog() { - if(mLog != null) { - // Start a new log (leaving the old one intact) - mLog = new OperationLog(); - mIndent = 0; - } - } - public OperationLog getLog() { return mLog; } @@ -825,6 +823,173 @@ public class ProviderHelper { } + public ConsolidateResult consolidateDatabase(Progressable progress) { + + // 1a. fetch all secret keyrings into a cache file + int numSecrets, numPublics; + + log(LogLevel.START, LogType.MSG_CON, mIndent); + mIndent += 1; + + try { + + log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_SECRET, mIndent); + mIndent += 1; + + final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] { + KeyRings.PRIVKEY_DATA, KeyRings.FINGERPRINT, KeyRings.HAS_ANY_SECRET + }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); + + if (cursor == null || !cursor.moveToFirst()) { + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + + numSecrets = cursor.getCount(); + + FileImportCache cache = + new FileImportCache(mContext, "consolidate_secret.pcl"); + cache.writeCache(new Iterator() { + ParcelableKeyRing ring; + + @Override + public boolean hasNext() { + if (ring != null) { + return true; + } + if (cursor.isAfterLast()) { + return false; + } + ring = new ParcelableKeyRing(cursor.getBlob(0), + PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1))); + cursor.moveToNext(); + return true; + } + + @Override + public ParcelableKeyRing next() { + try { + return ring; + } finally { + ring = null; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + }); + + } catch (IOException e) { + Log.e(Constants.TAG, "error saving secret"); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + + // 1b. fetch all public keyrings into a cache file + try { + + log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_PUBLIC, mIndent); + mIndent += 1; + + final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] { + KeyRings.PUBKEY_DATA, KeyRings.FINGERPRINT + }, null, null, null); + + if (cursor == null || !cursor.moveToFirst()) { + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + + numPublics = cursor.getCount(); + + FileImportCache cache = + new FileImportCache(mContext, "consolidate_public.pcl"); + cache.writeCache(new Iterator() { + ParcelableKeyRing ring; + + @Override + public boolean hasNext() { + if (ring != null) { + return true; + } + if (cursor.isAfterLast()) { + return false; + } + ring = new ParcelableKeyRing(cursor.getBlob(0), + PgpKeyHelper.convertFingerprintToHex(cursor.getBlob(1))); + cursor.moveToNext(); + return true; + } + + @Override + public ParcelableKeyRing next() { + try { + return ring; + } finally { + ring = null; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + }); + + } catch (IOException e) { + Log.e(Constants.TAG, "error saving public"); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + + // 2. wipe database (IT'S DANGEROUS) + log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR, mIndent); + new KeychainDatabase(mContext).clearDatabase(); + + // 3. Re-Import secret keyrings from cache + try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, mIndent, numSecrets); + mIndent += 1; + + FileImportCache cache = + new FileImportCache(mContext, "consolidate_secret.pcl"); + new PgpImportExport(mContext, this, new ProgressScaler(progress, 10, 25, 100)) + .importKeyRings(cache.readCache(), numSecrets); + } catch (IOException e) { + Log.e(Constants.TAG, "error importing secret"); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + + // 3. Re-Import public keyrings from cache + try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, mIndent, numPublics); + mIndent += 1; + + FileImportCache cache = + new FileImportCache(mContext, "consolidate_public.pcl"); + new PgpImportExport(mContext, this, new ProgressScaler(progress, 25, 99, 100)) + .importKeyRings(cache.readCache(), numPublics); + } catch (IOException e) { + Log.e(Constants.TAG, "error importing public"); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + + progress.setProgress(100, 100); + log(LogLevel.OK, LogType.MSG_CON_SUCCESS, mIndent); + mIndent -= 1; + + return new ConsolidateResult(ConsolidateResult.RESULT_OK, mLog); + + } + /** * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 0505a6339..9f5650df6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult; @@ -103,6 +104,8 @@ public class KeychainIntentService extends IntentService public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; + public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE"; + /* keys for data bundle */ // encrypt, decrypt, import export @@ -142,6 +145,7 @@ public class KeychainIntentService extends IntentService // import key public static final String IMPORT_KEY_LIST = "import_key_list"; + public static final String IMPORT_KEY_FILE = "import_key_file"; // export key public static final String EXPORT_OUTPUT_STREAM = "export_output_stream"; @@ -179,6 +183,8 @@ public class KeychainIntentService extends IntentService public static final String RESULT_IMPORT = "result"; + public static final String RESULT_CONSOLIDATE = "consolidate_result"; + Messenger mMessenger; private boolean mIsCanceled; @@ -662,7 +668,16 @@ public class KeychainIntentService extends IntentService } catch (Exception e) { sendErrorToHandler(e); } + + } else if (ACTION_CONSOLIDATE.equals(action)) { + ConsolidateResult result = new ProviderHelper(this).consolidateDatabase(this); + + Bundle resultData = new Bundle(); + resultData.putParcelable(RESULT_CONSOLIDATE, result); + + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } + } private void sendErrorToHandler(Exception e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 26fe63550..c601ec57e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -388,6 +388,15 @@ public class OperationResultParcel implements Parcelable { MSG_MF_UID_ERROR_EMPTY (R.string.msg_mf_uid_error_empty), MSG_MF_UNLOCK_ERROR (R.string.msg_mf_unlock_error), MSG_MF_UNLOCK (R.string.msg_mf_unlock), + + // consolidate + MSG_CON (R.string.msg_con), + MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret), + MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public), + MSG_CON_DB_CLEAR (R.string.msg_con_db_clear), + MSG_CON_REIMPORT_SECRET (R.plurals.msg_con_reimport_secret), + MSG_CON_REIMPORT_PUBLIC (R.plurals.msg_con_reimport_public), + MSG_CON_SUCCESS (R.string.msg_con_success), ; private final int mMsgId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 1fc496082..878f6ca47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -272,4 +272,12 @@ public abstract class OperationResults { }; } + public static class ConsolidateResult extends OperationResultParcel { + + public ConsolidateResult(int result, OperationLog log) { + super(result, log); + } + + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 7a6e78a7d..9d9462648 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -17,8 +17,11 @@ package org.sufficientlysecure.keychain.ui; +import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; import android.view.Menu; import android.view.MenuItem; @@ -28,6 +31,9 @@ import org.sufficientlysecure.keychain.helper.ExportHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -63,6 +69,7 @@ public class KeyListActivity extends DrawerActivity { getMenuInflater().inflate(R.menu.key_list, menu); if (Constants.DEBUG) { + menu.findItem(R.id.menu_key_list_debug_cons).setVisible(true); menu.findItem(R.id.menu_key_list_debug_read).setVisible(true); menu.findItem(R.id.menu_key_list_debug_write).setVisible(true); menu.findItem(R.id.menu_key_list_debug_first_time).setVisible(true); @@ -92,6 +99,10 @@ public class KeyListActivity extends DrawerActivity { mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true); return true; + case R.id.menu_key_list_debug_cons: + consolidate(); + return true; + case R.id.menu_key_list_debug_read: try { KeychainDatabase.debugBackup(this, true); @@ -136,4 +147,53 @@ public class KeyListActivity extends DrawerActivity { startActivity(intent); } + private void consolidate() { + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + this, + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; + } + final ConsolidateResult result = + returnData.getParcelable(KeychainIntentService.RESULT_CONSOLIDATE); + if (result == null) { + return; + } + + result.createNotify(KeyListActivity.this).show(); + } + } + }; + + // Send all information needed to service to import key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_CONSOLIDATE); + + // fill values for this action + Bundle data = new Bundle(); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + + } + } -- cgit v1.2.3 From 3cc57a092a7ba59390b2d892db028cc1990cdbd1 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 17 Aug 2014 11:07:34 +0200 Subject: Remove NoSwipeWrapContentViewPager --- .../keychain/ui/EncryptActivity.java | 41 +++++++------- .../ui/widget/NoSwipeWrapContentViewPager.java | 62 ---------------------- 2 files changed, 20 insertions(+), 83 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 7e08f6b7c..59a433af3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -73,16 +73,13 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryption_key_ids"; // view - ViewPager mViewPagerMode; - //PagerTabStrip mPagerTabStripMode; - PagerTabStripAdapter mTabsAdapterMode; - ViewPager mViewPagerContent; - PagerTabStrip mPagerTabStripContent; - PagerTabStripAdapter mTabsAdapterContent; + private int mCurrentMode = PAGER_MODE_ASYMMETRIC; + private ViewPager mViewPagerContent; + private PagerTabStrip mPagerTabStripContent; + private PagerTabStripAdapter mTabsAdapterContent; // tabs - int mSwitchToMode = PAGER_MODE_ASYMMETRIC; - int mSwitchToContent = PAGER_CONTENT_MESSAGE; + private int mSwitchToContent = PAGER_CONTENT_MESSAGE; private static final int PAGER_MODE_ASYMMETRIC = 0; private static final int PAGER_MODE_SYMMETRIC = 1; @@ -102,7 +99,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn private String mMessage = ""; public boolean isModeSymmetric() { - return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); + return PAGER_MODE_SYMMETRIC == mCurrentMode; } public boolean isContentMessage() { @@ -474,13 +471,9 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } private void initView() { - mViewPagerMode = (ViewPager) findViewById(R.id.encrypt_pager_mode); - //mPagerTabStripMode = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_mode); mViewPagerContent = (ViewPager) findViewById(R.id.encrypt_pager_content); mPagerTabStripContent = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_content); - mTabsAdapterMode = new PagerTabStripAdapter(this); - mViewPagerMode.setAdapter(mTabsAdapterMode); mTabsAdapterContent = new PagerTabStripAdapter(this); mViewPagerContent.setAdapter(mTabsAdapterContent); } @@ -502,10 +495,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn // Handle intent actions handleActions(getIntent()); - - mTabsAdapterMode.addTab(EncryptAsymmetricFragment.class, null, getString(R.string.label_asymmetric)); - mTabsAdapterMode.addTab(EncryptSymmetricFragment.class, null, getString(R.string.label_symmetric)); - mViewPagerMode.setCurrentItem(mSwitchToMode); + updateModeFragment(); mTabsAdapterContent.addTab(EncryptMessageFragment.class, null, getString(R.string.label_message)); mTabsAdapterContent.addTab(EncryptFileFragment.class, null, getString(R.string.label_files)); @@ -521,6 +511,16 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn return super.onCreateOptionsMenu(menu); } + private void updateModeFragment() { + getSupportFragmentManager().beginTransaction() + .replace(R.id.encrypt_pager_mode, + mCurrentMode == PAGER_MODE_SYMMETRIC + ? new EncryptSymmetricFragment() + : new EncryptAsymmetricFragment()) + .commitAllowingStateLoss(); + getSupportFragmentManager().executePendingTransactions(); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.isCheckable()) { @@ -528,9 +528,8 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn } switch (item.getItemId()) { case R.id.check_use_symmetric: - mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; - - mViewPagerMode.setCurrentItem(mSwitchToMode); + mCurrentMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; + updateModeFragment(); notifyUpdate(); break; case R.id.check_use_armor: @@ -604,7 +603,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); // preselect keys given by intent - mSwitchToMode = PAGER_MODE_ASYMMETRIC; + mCurrentMode = PAGER_MODE_ASYMMETRIC; /** * Main Actions diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java deleted file mode 100644 index a48d2a026..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -public class NoSwipeWrapContentViewPager extends android.support.v4.view.ViewPager { - public NoSwipeWrapContentViewPager(Context context) { - super(context); - } - - public NoSwipeWrapContentViewPager(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - - int height; - View child = getChildAt(getCurrentItem()); - if (child != null) { - child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - height = child.getMeasuredHeight(); - } else { - height = 0; - } - - heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent arg0) { - // Never allow swiping to switch between pages - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - // Never allow swiping to switch between pages - return false; - } -} -- cgit v1.2.3 From 57b2440731ebed567c59ae16c1f669fb47d0544f Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 17 Aug 2014 11:31:41 +0200 Subject: Work-around rendering bug when switching back to asymmetric with multiple recipients selected --- .../keychain/ui/EncryptAsymmetricFragment.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 748cbca14..a508472d6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -18,30 +18,16 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; -import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.Spinner; -import android.widget.SpinnerAdapter; -import android.widget.TextView; import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -169,6 +155,8 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi Log.e(Constants.TAG, "key not found!", e); } } + // This is to work-around a rendering bug in TokenCompleteTextView + mEncryptKeyView.requestFocus(); updateEncryptionKeys(); } } -- cgit v1.2.3 From 3e7ce0008fde176634980a31f61052052698ff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 18 Aug 2014 11:02:41 +0200 Subject: Fixes for expiry UI --- .../keychain/ui/EditKeyFragment.java | 4 +- .../keychain/ui/adapter/SubkeysAdapter.java | 8 +- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 8 +- .../ui/dialog/AddSubkeyDialogFragment.java | 5 +- .../ui/dialog/EditSubkeyExpiryDialogFragment.java | 145 ++++++++++++--------- 5 files changed, 101 insertions(+), 69 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 409953ad5..f2d6d4c13 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -406,10 +406,10 @@ public class EditKeyFragment extends LoaderFragment implements @Override public void handleMessage(Message message) { switch (message.what) { - case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: + case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY: mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = (Long) message.getData().getSerializable( - EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); + EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY); break; } getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 6df84a056..9958b33a1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -35,7 +35,9 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import java.util.Calendar; import java.util.Date; +import java.util.TimeZone; public class SubkeysAdapter extends CursorAdapter { private LayoutInflater mInflater; @@ -198,9 +200,13 @@ public class SubkeysAdapter extends CursorAdapter { boolean isExpired; if (expiryDate != null) { isExpired = expiryDate.before(new Date()); + Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + expiryCal.setTime(expiryDate); + // convert from UTC to time zone of device + expiryCal.setTimeZone(TimeZone.getDefault()); vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " - + DateFormat.getDateFormat(context).format(expiryDate)); + + DateFormat.getDateFormat(context).format(expiryCal.getTime())); } else { isExpired = false; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java index 7e0027ddc..a1dfeb10c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -33,8 +33,10 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.TimeZone; public class SubkeysAddedAdapter extends ArrayAdapter { private LayoutInflater mInflater; @@ -108,9 +110,13 @@ public class SubkeysAddedAdapter extends ArrayAdapter= android.os.Build.VERSION_CODES.HONEYCOMB) { - mExpiryDatePicker.setMinDate(new Date().getTime() + DateUtils.DAY_IN_MILLIS); + // date picker works based on default time zone + Calendar minDateCal = Calendar.getInstance(TimeZone.getDefault()); + minDateCal.add(Calendar.DAY_OF_YEAR, 1); // at least one day after creation (today) + mExpiryDatePicker.setMinDate(minDateCal.getTime().getTime()); } ArrayList choices = new ArrayList(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java index fde8a3477..f46e253c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -25,9 +25,10 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; -import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.DatePicker; import org.sufficientlysecure.keychain.Constants; @@ -40,17 +41,15 @@ import java.util.TimeZone; public class EditSubkeyExpiryDialogFragment extends DialogFragment { private static final String ARG_MESSENGER = "messenger"; - private static final String ARG_CREATION_DATE = "creation_date"; - private static final String ARG_EXPIRY_DATE = "expiry_date"; + private static final String ARG_CREATION = "creation"; + private static final String ARG_EXPIRY = "expiry"; - public static final int MESSAGE_NEW_EXPIRY_DATE = 1; + public static final int MESSAGE_NEW_EXPIRY = 1; public static final int MESSAGE_CANCEL = 2; - public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; + public static final String MESSAGE_DATA_EXPIRY = "expiry"; private Messenger mMessenger; - private DatePicker mDatePicker; - /** * Creates new instance of this dialog fragment */ @@ -59,8 +58,8 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { EditSubkeyExpiryDialogFragment frag = new EditSubkeyExpiryDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); - args.putSerializable(ARG_CREATION_DATE, creationDate); - args.putSerializable(ARG_EXPIRY_DATE, expiryDate); + args.putSerializable(ARG_CREATION, creationDate); + args.putSerializable(ARG_EXPIRY, expiryDate); frag.setArguments(args); @@ -74,13 +73,13 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); mMessenger = getArguments().getParcelable(ARG_MESSENGER); - long creationDate = getArguments().getLong(ARG_CREATION_DATE); - long expiryDate = getArguments().getLong(ARG_EXPIRY_DATE); + long creation = getArguments().getLong(ARG_CREATION); + long expiry = getArguments().getLong(ARG_EXPIRY); Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(new Date(creationDate * 1000)); + creationCal.setTime(new Date(creation * 1000)); final Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - expiryCal.setTime(new Date(expiryDate * 1000)); + expiryCal.setTime(new Date(expiry * 1000)); // date picker works with default time zone, we need to convert from UTC to default timezone creationCal.setTimeZone(TimeZone.getDefault()); @@ -96,44 +95,64 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { View view = inflater.inflate(R.layout.edit_subkey_expiry_dialog, null); alert.setView(view); - mDatePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker); + final CheckBox noExpiry = (CheckBox) view.findViewById(R.id.edit_subkey_expiry_no_expiry); + final DatePicker datePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker); - // set default date - if (expiryDate == 0L) { - // if key has no expiry, set it to creation date +1 day + noExpiry.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + datePicker.setVisibility(View.GONE); + } else { + datePicker.setVisibility(View.VISIBLE); + } + } + }); - Calendar creationCalPlusOne = (Calendar) creationCal.clone(); - creationCalPlusOne.add(Calendar.DAY_OF_MONTH, 1); - mDatePicker.init( - creationCalPlusOne.get(Calendar.YEAR), - creationCalPlusOne.get(Calendar.MONTH), - creationCalPlusOne.get(Calendar.DAY_OF_MONTH), - null - ); + // init date picker with default selected date + if (expiry == 0L) { + noExpiry.setChecked(true); + datePicker.setVisibility(View.GONE); + + Calendar todayCal = Calendar.getInstance(TimeZone.getDefault()); + if (creationCal.after(todayCal)) { + // Note: This is just for the rare cases where creation is _after_ today + + // set it to creation date +1 day (don't set it to creationCal, it would break crash + // datePicker.setMinDate() execution with IllegalArgumentException + Calendar creationCalPlusOne = (Calendar) creationCal.clone(); + creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1); + datePicker.init( + creationCalPlusOne.get(Calendar.YEAR), + creationCalPlusOne.get(Calendar.MONTH), + creationCalPlusOne.get(Calendar.DAY_OF_MONTH), + null + ); + + } else { + // normally, just init with today + datePicker.init( + todayCal.get(Calendar.YEAR), + todayCal.get(Calendar.MONTH), + todayCal.get(Calendar.DAY_OF_MONTH), + null + ); + } } else { - // set date picker to current expiry date +1 day - - Calendar expiryCalPlusOne = (Calendar) expiryCal.clone(); - expiryCalPlusOne.add(Calendar.DAY_OF_MONTH, 1); - mDatePicker.init( - expiryCalPlusOne.get(Calendar.YEAR), - expiryCalPlusOne.get(Calendar.MONTH), - expiryCalPlusOne.get(Calendar.DAY_OF_MONTH), + noExpiry.setChecked(false); + datePicker.setVisibility(View.VISIBLE); + + // set date picker to current expiry + datePicker.init( + expiryCal.get(Calendar.YEAR), + expiryCal.get(Calendar.MONTH), + expiryCal.get(Calendar.DAY_OF_MONTH), null ); } if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // will crash with IllegalArgumentException if we set a min date - // that is before creation date - if (expiryDate == 0L || creationCal.before(expiryCal)) { - mDatePicker.setMinDate(creationCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } else { - // set min to expiry date - mDatePicker.setMinDate(expiryCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } + datePicker.setMinDate(creationCal.getTime().getTime()); } alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -141,30 +160,28 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment { public void onClick(DialogInterface dialog, int id) { dismiss(); - Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); - //noinspection ResourceType - selectedCal.set(mDatePicker.getYear(), mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); - // date picker uses default time zone, we need to convert to UTC - selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); - - long numDays = (selectedCal.getTimeInMillis() / 86400000) - - (expiryCal.getTimeInMillis() / 86400000); - if (numDays > 0) { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + long expiry; + if (noExpiry.isChecked()) { + expiry = 0L; + } else { + Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); + //noinspection ResourceType + selectedCal.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth()); + // date picker uses default time zone, we need to convert to UTC + selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); + + long numDays = (selectedCal.getTimeInMillis() / 86400000) + - (expiryCal.getTimeInMillis() / 86400000); + if (numDays <= 0) { + Log.e(Constants.TAG, "Should not happen! Expiry num of days <= 0!"); + throw new RuntimeException(); + } + expiry = selectedCal.getTime().getTime() / 1000; } - } - }); - - alert.setNeutralButton(R.string.btn_no_date, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dismiss(); Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, 0L); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + data.putSerializable(MESSAGE_DATA_EXPIRY, expiry); + sendMessageToHandler(MESSAGE_NEW_EXPIRY, data); } }); -- cgit v1.2.3 From a5d34478dfdc37c4345d43bbb8a362f8be721ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 18 Aug 2014 11:13:52 +0200 Subject: Add subkey: at least one flag should be selected! --- .../ui/dialog/AddSubkeyDialogFragment.java | 127 ++++++++++++--------- 1 file changed, 74 insertions(+), 53 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index d5c80d18a..450e6a5f5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -33,6 +33,7 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.DatePicker; @@ -40,6 +41,7 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.TableRow; import android.widget.TextView; +import android.widget.Toast; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; @@ -167,60 +169,11 @@ public class AddSubkeyDialogFragment extends DialogFragment { mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length - dialog.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); - int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); - - int flags = 0; - if (mFlagCertify.isChecked()) { - flags |= KeyFlags.CERTIFY_OTHER; - } - if (mFlagSign.isChecked()) { - flags |= KeyFlags.SIGN_DATA; - } - if (mFlagEncrypt.isChecked()) { - flags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE; - } - if (mFlagAuthenticate.isChecked()) { - flags |= KeyFlags.AUTHENTICATION; - } - - long expiry; - if (mNoExpiryCheckBox.isChecked()) { - expiry = 0L; - } else { - Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); - //noinspection ResourceType - selectedCal.set(mExpiryDatePicker.getYear(), - mExpiryDatePicker.getMonth(), mExpiryDatePicker.getDayOfMonth()); - // date picker uses default time zone, we need to convert to UTC - selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); - - expiry = selectedCal.getTime().getTime() / 1000; - } - - SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd( - newKeyAlgorithmChoice.getId(), - newKeySize, - flags, - expiry - ); - mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey); - } - } - ); - dialog.setCancelable(true); - dialog.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - } - } - ); + + // onClickListener are set in onStart() to override default dismiss behaviour + dialog.setPositiveButton(android.R.string.ok, null); + dialog.setNegativeButton(android.R.string.cancel, null); final AlertDialog alertDialog = dialog.show(); @@ -268,6 +221,74 @@ public class AddSubkeyDialogFragment extends DialogFragment { return alertDialog; } + @Override + public void onStart() { + super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point + AlertDialog d = (AlertDialog) getDialog(); + if (d != null) { + Button positiveButton = d.getButton(Dialog.BUTTON_POSITIVE); + Button negativeButton = d.getButton(Dialog.BUTTON_NEGATIVE); + positiveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mFlagCertify.isChecked() && !mFlagSign.isChecked() + && !mFlagEncrypt.isChecked() && !mFlagAuthenticate.isChecked()) { + Toast.makeText(getActivity(), R.string.edit_key_select_flag, Toast.LENGTH_LONG).show(); + return; + } + + // dismiss only if at least one flag is selected + dismiss(); + + Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); + int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); + + int flags = 0; + if (mFlagCertify.isChecked()) { + flags |= KeyFlags.CERTIFY_OTHER; + } + if (mFlagSign.isChecked()) { + flags |= KeyFlags.SIGN_DATA; + } + if (mFlagEncrypt.isChecked()) { + flags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE; + } + if (mFlagAuthenticate.isChecked()) { + flags |= KeyFlags.AUTHENTICATION; + } + + long expiry; + if (mNoExpiryCheckBox.isChecked()) { + expiry = 0L; + } else { + Calendar selectedCal = Calendar.getInstance(TimeZone.getDefault()); + //noinspection ResourceType + selectedCal.set(mExpiryDatePicker.getYear(), + mExpiryDatePicker.getMonth(), mExpiryDatePicker.getDayOfMonth()); + // date picker uses default time zone, we need to convert to UTC + selectedCal.setTimeZone(TimeZone.getTimeZone("UTC")); + + expiry = selectedCal.getTime().getTime() / 1000; + } + + SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd( + newKeyAlgorithmChoice.getId(), + newKeySize, + flags, + expiry + ); + mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey); + } + }); + negativeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } + } + private int getSelectedKeyLength() { final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); final String customLengthString = getResources().getString(R.string.key_size_custom); -- cgit v1.2.3 From 6ffdafc0e6cd12a9a65f8eea4f74212312bba55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 10:01:39 +0200 Subject: Add license headers --- .../keychain/ui/widget/CertifyKeySpinner.java | 17 +++++++++++++++++ .../keychain/ui/widget/KeySpinner.java | 17 +++++++++++++++++ .../keychain/ui/widget/SignKeySpinner.java | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 030a76136..e3c9804bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + package org.sufficientlysecure.keychain.ui.widget; import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index b12029239..3a31fc9f4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + package org.sufficientlysecure.keychain.ui.widget; import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index cbec7f920..a1ed2c065 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + package org.sufficientlysecure.keychain.ui.widget; import android.content.Context; -- cgit v1.2.3 From a2b38245567ec314cbe1d428d8ad2082d1148134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 10:30:44 +0200 Subject: New preferred hash and symmetric algos, removed SHA-1, 3DES, new ordering --- .../keychain/pgp/PgpKeyOperation.java | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index cdd2eacc0..c6c064a25 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -84,15 +84,25 @@ import java.util.Stack; public class PgpKeyOperation { private Stack mProgress; + // most preferred is first private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{ - SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192, - SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5, - SymmetricKeyAlgorithmTags.TRIPLE_DES}; - private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{HashAlgorithmTags.SHA1, - HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160}; + SymmetricKeyAlgorithmTags.AES_256, + SymmetricKeyAlgorithmTags.AES_192, + SymmetricKeyAlgorithmTags.AES_128, + SymmetricKeyAlgorithmTags.CAST5 + }; + private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ + HashAlgorithmTags.SHA512, + HashAlgorithmTags.SHA384, + HashAlgorithmTags.SHA224, + HashAlgorithmTags.SHA256, + HashAlgorithmTags.RIPEMD160 + }; private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{ - CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2, - CompressionAlgorithmTags.ZIP}; + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2, + CompressionAlgorithmTags.ZIP + }; public PgpKeyOperation(Progressable progress) { super(); -- cgit v1.2.3 From 2c8bcffff3d04a84e7fb51efac6b099a477a98f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 10:37:27 +0200 Subject: add feature to key sig subpacket to indicate that we want MDC --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index c6c064a25..7dedcb242 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -22,6 +22,7 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; +import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; import org.spongycastle.openpgp.PGPEncryptedData; @@ -894,6 +895,8 @@ public class PgpKeyOperation { hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); + // Request senders add additional checksums to the message (useful when verifying unsigned messages.) + hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION); hashedPacketsGen.setPrimaryUserID(false, primary); hashedPacketsGen.setKeyFlags(false, flags); if (expiry > 0) { -- cgit v1.2.3 From b1bde6ead93f61d471c7fcd183c50da81d7ee848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 10:42:35 +0200 Subject: Mark packets critical --- .../keychain/pgp/PgpKeyOperation.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 7dedcb242..c1c261126 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -891,17 +891,17 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); { - hashedPacketsGen.setSignatureCreationTime(false, new Date()); + hashedPacketsGen.setSignatureCreationTime(true, new Date()); hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); - // Request senders add additional checksums to the message (useful when verifying unsigned messages.) + // Request that senders add the MDC to the message (useful when verifying unsigned messages.) hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION); - hashedPacketsGen.setPrimaryUserID(false, primary); - hashedPacketsGen.setKeyFlags(false, flags); + hashedPacketsGen.setPrimaryUserID(true, primary); + hashedPacketsGen.setKeyFlags(true, flags); if (expiry > 0) { hashedPacketsGen.setKeyExpirationTime( - false, expiry - pKey.getCreationTime().getTime() / 1000); + true, expiry - pKey.getCreationTime().getTime() / 1000); } } @@ -918,7 +918,7 @@ public class PgpKeyOperation { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); - subHashedPacketsGen.setSignatureCreationTime(false, new Date()); + subHashedPacketsGen.setSignatureCreationTime(true, new Date()); sGen.setHashedSubpackets(subHashedPacketsGen.generate()); sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey); return sGen.generateCertification(userId, pKey); @@ -932,7 +932,7 @@ public class PgpKeyOperation { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); - subHashedPacketsGen.setSignatureCreationTime(false, new Date()); + subHashedPacketsGen.setSignatureCreationTime(true, new Date()); sGen.setHashedSubpackets(subHashedPacketsGen.generate()); // Generate key revocation or subkey revocation, depending on master/subkey-ness if (masterPublicKey.getKeyID() == pKey.getKeyID()) { @@ -978,16 +978,16 @@ public class PgpKeyOperation { sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey); sGen.setHashedSubpackets(subHashedPacketsGen.generate()); PGPSignature certification = sGen.generateCertification(masterPublicKey, pKey); - unhashedPacketsGen.setEmbeddedSignature(false, certification); + unhashedPacketsGen.setEmbeddedSignature(true, certification); } PGPSignatureSubpacketGenerator hashedPacketsGen; { hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setSignatureCreationTime(false, creationTime); - hashedPacketsGen.setKeyFlags(false, flags); + hashedPacketsGen.setSignatureCreationTime(true, creationTime); + hashedPacketsGen.setKeyFlags(true, flags); if (expiry > 0) { - hashedPacketsGen.setKeyExpirationTime(false, + hashedPacketsGen.setKeyExpirationTime(true, expiry - pKey.getCreationTime().getTime() / 1000); } } -- cgit v1.2.3 From d131693bb89f2bddd194993be45aeb13402196a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 10:58:38 +0200 Subject: Use SHA512 instead of SHA1 and AES256 instead of CAST5 where possible --- .../keychain/pgp/PgpKeyOperation.java | 42 +++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index c1c261126..b143085d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -35,7 +35,6 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; -import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; @@ -250,13 +249,16 @@ public class PgpKeyOperation { progress(R.string.progress_building_master_key, 40); - // define hashing and signing algos - PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA1); // Build key encrypter and decrypter based on passphrase + PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(HashAlgorithmTags.SHA512); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.CAST5, sha1Calc) + PGPEncryptedData.AES_256, sha512Calc) .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); PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), sha1Calc, true, keyEncryptor); @@ -702,17 +704,17 @@ public class PgpKeyOperation { pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert); PGPSecretKey sKey; { - // define hashing and signing algos - PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA1); - // Build key encrypter and decrypter based on passphrase + PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(HashAlgorithmTags.SHA512); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.CAST5, sha1Calc) + PGPEncryptedData.AES_256, sha512Calc) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, - sha1Calc, false, keyEncryptor); + // NOTE: only SHA1 is supported for key checksum calculations. + PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(HashAlgorithmTags.SHA1); + sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, sha1Calc, false, keyEncryptor); } log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID, @@ -729,13 +731,13 @@ public class PgpKeyOperation { log.add(LogLevel.INFO, LogType.MSG_MF_PASSPHRASE, indent); indent += 1; - PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build() - .get(HashAlgorithmTags.SHA1); + PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder().build() + .get(HashAlgorithmTags.SHA512); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); // Build key encryptor based on new passphrase PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.CAST5, sha1Calc) + PGPEncryptedData.AES_256, sha512Calc) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( saveParcel.mNewPassphrase.toCharArray()); @@ -885,7 +887,7 @@ public class PgpKeyOperation { int flags, long expiry) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); @@ -914,7 +916,7 @@ public class PgpKeyOperation { PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), PGPUtil.SHA1) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -928,7 +930,7 @@ public class PgpKeyOperation { PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPublicKey.getAlgorithm(), PGPUtil.SHA1) + masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA512) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -972,7 +974,7 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); subHashedPacketsGen.setSignatureCreationTime(false, creationTime); PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PGPUtil.SHA1) + pKey.getAlgorithm(), HashAlgorithmTags.SHA512) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey); @@ -993,7 +995,7 @@ public class PgpKeyOperation { } PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPublicKey.getAlgorithm(), PGPUtil.SHA1) + masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA512) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey); -- cgit v1.2.3 From 4a280f6ba36f35d21e87642d74d3e9dfdf6f09d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 11:11:58 +0200 Subject: Use higher s2k count --- .../keychain/pgp/PgpKeyOperation.java | 39 ++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index b143085d5..c69eeaf04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -25,7 +25,6 @@ import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; -import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPKeyPair; import org.spongycastle.openpgp.PGPPrivateKey; @@ -104,6 +103,26 @@ public class PgpKeyOperation { 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. I'll use 0xc0 as a + * default -- about 130,000 iterations. + * + * http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html + */ + private static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA512; + private static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; + private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0xc0; + public PgpKeyOperation(Progressable progress) { super(); if (progress != null) { @@ -250,10 +269,10 @@ public class PgpKeyOperation { progress(R.string.progress_building_master_key, 40); // Build key encrypter and decrypter based on passphrase - PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA512); + PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.AES_256, sha512Calc) + SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); // NOTE: only SHA1 is supported for key checksum calculations. @@ -705,10 +724,10 @@ public class PgpKeyOperation { PGPSecretKey sKey; { // Build key encrypter and decrypter based on passphrase - PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA512); + PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.AES_256, sha512Calc) + SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); // NOTE: only SHA1 is supported for key checksum calculations. @@ -731,13 +750,13 @@ public class PgpKeyOperation { log.add(LogLevel.INFO, LogType.MSG_MF_PASSPHRASE, indent); indent += 1; - PGPDigestCalculator sha512Calc = new JcaPGPDigestCalculatorProviderBuilder().build() - .get(HashAlgorithmTags.SHA512); + PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build() + .get(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( - PGPEncryptedData.AES_256, sha512Calc) + SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( saveParcel.mNewPassphrase.toCharArray()); -- cgit v1.2.3 From c1d05d0ee92e9c9bc2a12a64aa4b73e832fbde0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 14:16:30 +0200 Subject: Change criticallity of subpackets after discussion --- .../org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index c69eeaf04..85e772d52 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -913,12 +913,12 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); { hashedPacketsGen.setSignatureCreationTime(true, new Date()); - hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); - hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); - hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); - // Request that senders add the MDC to the message (useful when verifying unsigned messages.) + hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS); + hashedPacketsGen.setPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS); + hashedPacketsGen.setPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS); + // Request that senders add the MDC to the message (authenticate unsigned messages) hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION); - hashedPacketsGen.setPrimaryUserID(true, primary); + hashedPacketsGen.setPrimaryUserID(false, primary); hashedPacketsGen.setKeyFlags(true, flags); if (expiry > 0) { hashedPacketsGen.setKeyExpirationTime( -- cgit v1.2.3 From 6a3150d8788664a5e1d501488159ff5e080cb9b4 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 14:42:40 +0200 Subject: fix primary user id in master key flag modification --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index c69eeaf04..88c6437d3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -881,10 +881,12 @@ public class PgpKeyOperation { } // add shiny new user id certificate + boolean isPrimary = currentCert.getHashedSubPackets() != null && + currentCert.getHashedSubPackets().isPrimaryUserID(); modifiedPublicKey = PGPPublicKey.removeCertification( modifiedPublicKey, userId, currentCert); PGPSignature newCert = generateUserIdSignature( - masterPrivateKey, masterPublicKey, userId, true, flags, expiry); + masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry); modifiedPublicKey = PGPPublicKey.addCertification( modifiedPublicKey, userId, newCert); ok = true; -- cgit v1.2.3 From 9474749be15b49c89b6e2de820f62b2e0029f393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 14:51:28 +0200 Subject: Decrease iteration count, delayed for 2.9 --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 913bfafed..6228b36ac 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -121,7 +121,7 @@ public class PgpKeyOperation { */ private static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA512; private static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; - private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0xc0; + private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x60; public PgpKeyOperation(Progressable progress) { super(); -- cgit v1.2.3 From 8d668d170c41959897aa78e2f0acc9fac7168d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 15:23:37 +0200 Subject: Notes about criticality --- .../keychain/pgp/PgpKeyOperation.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 6228b36ac..b4e21cc0e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -914,13 +914,26 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); { - hashedPacketsGen.setSignatureCreationTime(true, new Date()); + /* + * From RFC about critical subpackets: + * If a subpacket is encountered that is + * marked critical but is unknown to the evaluating software, the + * evaluator SHOULD consider the signature to be in error. + * An evaluator may "recognize" a subpacket, but not implement it. The + * purpose of the critical bit is to allow the signer to tell an + * evaluator that it would prefer a new, unknown feature to generate an + * 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.setPrimaryUserID(false, primary); + + /* critical subpackets: */ + hashedPacketsGen.setSignatureCreationTime(true, new Date()); // Request that senders add the MDC to the message (authenticate unsigned messages) hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION); - hashedPacketsGen.setPrimaryUserID(false, primary); hashedPacketsGen.setKeyFlags(true, flags); if (expiry > 0) { hashedPacketsGen.setKeyExpirationTime( -- cgit v1.2.3 From c725239a69544213229e2d1d0b69b4dca0bcc5d9 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 15:45:42 +0200 Subject: consolidate: split into two steps, can pick up at second step if anything fails --- .../org/sufficientlysecure/keychain/Constants.java | 3 + .../keychain/helper/Preferences.java | 31 +++++++++++ .../keychain/provider/ProviderHelper.java | 65 +++++++++++++++++----- .../keychain/service/KeychainIntentService.java | 13 +---- .../keychain/service/OperationResultParcel.java | 1 + .../keychain/util/FileImportCache.java | 22 +++++++- 6 files changed, 109 insertions(+), 26 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index bce093427..78b66464b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -68,6 +68,9 @@ public final class Constants { public static final String KEY_SERVERS_DEFAULT_VERSION = "keyServersDefaultVersion"; public static final String WRITE_VERSION_HEADER = "writeVersionHeader"; public static final String FIRST_TIME = "firstTime"; + public static final String CACHED_CONSOLIDATE = "cachedConsolidate"; + public static final String CACHED_CONSOLIDATE_SECRETS = "cachedConsolidateSecrets"; + public static final String CACHED_CONSOLIDATE_PUBLICS = "cachedConsolidatePublics"; } public static final class Defaults { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index 14ae46840..9a10148f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -25,6 +25,7 @@ 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.Pref; import java.util.ArrayList; import java.util.Arrays; @@ -134,6 +135,36 @@ public class Preferences { editor.commit(); } + public boolean getCachedConsolidate() { + return mSharedPreferences.getBoolean(Pref.CACHED_CONSOLIDATE, false); + } + + public void setCachedConsolidate(boolean value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(Pref.CACHED_CONSOLIDATE, value); + editor.commit(); + } + + public int getCachedConsolidateNumPublics() { + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_PUBLICS, 100); + } + + public void setCachedConsolidateNumPublics(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Pref.CACHED_CONSOLIDATE_PUBLICS, value); + editor.commit(); + } + + public int getCachedConsolidateNumSecrets() { + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_SECRETS, 100); + } + + public void setCachedConsolidateNumSecrets(int value) { + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(Pref.CACHED_CONSOLIDATE_SECRETS, value); + editor.commit(); + } + public boolean isFirstTime() { return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 3594ded51..5f55eedd5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -28,6 +28,8 @@ import android.os.RemoteException; import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; @@ -58,6 +60,7 @@ import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResul import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ProgressFixedScaler; import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayOutputStream; @@ -823,11 +826,9 @@ public class ProviderHelper { } - public ConsolidateResult consolidateDatabase(Progressable progress) { + public ConsolidateResult consolidateDatabaseStep1(Progressable progress) { // 1a. fetch all secret keyrings into a cache file - int numSecrets, numPublics; - log(LogLevel.START, LogType.MSG_CON, mIndent); mIndent += 1; @@ -836,7 +837,7 @@ public class ProviderHelper { log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_SECRET, mIndent); mIndent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] { + final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ KeyRings.PRIVKEY_DATA, KeyRings.FINGERPRINT, KeyRings.HAS_ANY_SECRET }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); @@ -844,7 +845,7 @@ public class ProviderHelper { return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } - numSecrets = cursor.getCount(); + Preferences.getPreferences(mContext).setCachedConsolidateNumSecrets(cursor.getCount()); FileImportCache cache = new FileImportCache(mContext, "consolidate_secret.pcl"); @@ -894,7 +895,7 @@ public class ProviderHelper { log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_PUBLIC, mIndent); mIndent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] { + final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ KeyRings.PUBKEY_DATA, KeyRings.FINGERPRINT }, null, null, null); @@ -902,7 +903,7 @@ public class ProviderHelper { return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } - numPublics = cursor.getCount(); + Preferences.getPreferences(mContext).setCachedConsolidateNumSecrets(cursor.getCount()); FileImportCache cache = new FileImportCache(mContext, "consolidate_public.pcl"); @@ -946,19 +947,39 @@ public class ProviderHelper { mIndent -= 1; } + Preferences.getPreferences(mContext).setCachedConsolidate(true); + + return consolidateDatabaseStep2(progress); + } + + public ConsolidateResult consolidateDatabaseStep2(Progressable progress) { + + Preferences prefs = Preferences.getPreferences(mContext); + if ( ! prefs.getCachedConsolidate()) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_BAD_STATE); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + + // Set flag that we have a cached consolidation here + int numSecrets = prefs.getCachedConsolidateNumSecrets(); + int numPublics = prefs.getCachedConsolidateNumPublics(); + // 2. wipe database (IT'S DANGEROUS) log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR, mIndent); new KeychainDatabase(mContext).clearDatabase(); + FileImportCache cacheSecret = + new FileImportCache(mContext, "consolidate_secret.pcl"); + FileImportCache cachePublic = + new FileImportCache(mContext, "consolidate_public.pcl"); + // 3. Re-Import secret keyrings from cache try { log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, mIndent, numSecrets); mIndent += 1; - FileImportCache cache = - new FileImportCache(mContext, "consolidate_secret.pcl"); - new PgpImportExport(mContext, this, new ProgressScaler(progress, 10, 25, 100)) - .importKeyRings(cache.readCache(), numSecrets); + new PgpImportExport(mContext, this, new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) + .importKeyRings(cacheSecret.readCache(false), numSecrets); } catch (IOException e) { Log.e(Constants.TAG, "error importing secret"); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); @@ -966,15 +987,13 @@ public class ProviderHelper { mIndent -= 1; } - // 3. Re-Import public keyrings from cache + // 4. Re-Import public keyrings from cache try { log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, mIndent, numPublics); mIndent += 1; - FileImportCache cache = - new FileImportCache(mContext, "consolidate_public.pcl"); new PgpImportExport(mContext, this, new ProgressScaler(progress, 25, 99, 100)) - .importKeyRings(cache.readCache(), numPublics); + .importKeyRings(cachePublic.readCache(false), numPublics); } catch (IOException e) { Log.e(Constants.TAG, "error importing public"); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); @@ -982,6 +1001,22 @@ public class ProviderHelper { mIndent -= 1; } + Preferences.getPreferences(mContext).setCachedConsolidate(false); + + // 5. Delete caches + try { + cacheSecret.delete(); + } catch (IOException e) { + // doesn't really matter + Log.e(Constants.TAG, "IOException during delete of secret cache", e); + } + try { + cachePublic.delete(); + } catch (IOException e) { + // doesn't really matter + Log.e(Constants.TAG, "IOException during deletion of public cache", e); + } + progress.setProgress(100, 100); log(LogLevel.OK, LogType.MSG_CON_SUCCESS, mIndent); mIndent -= 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 9f5650df6..2c1bc8463 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -490,10 +490,7 @@ public class KeychainIntentService extends IntentService PgpImportExport pgpImportExport = new PgpImportExport(this, this); ImportKeyResult result = pgpImportExport.importKeyRings(entries); - Bundle resultData = new Bundle(); - resultData.putParcelable(RESULT_IMPORT, result); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } catch (Exception e) { sendErrorToHandler(e); } @@ -670,12 +667,8 @@ public class KeychainIntentService extends IntentService } } else if (ACTION_CONSOLIDATE.equals(action)) { - ConsolidateResult result = new ProviderHelper(this).consolidateDatabase(this); - - Bundle resultData = new Bundle(); - resultData.putParcelable(RESULT_CONSOLIDATE, result); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + ConsolidateResult result = new ProviderHelper(this).consolidateDatabaseStep1(this); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index c601ec57e..3f478cfed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -391,6 +391,7 @@ public class OperationResultParcel implements Parcelable { // consolidate MSG_CON (R.string.msg_con), + MSG_CON_ERROR_BAD_STATE (R.string.msg_con_error_bad_state), MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret), MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public), MSG_CON_DB_CLEAR (R.string.msg_con_db_clear), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java index 35833adc6..09275fc95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileImportCache.java @@ -92,6 +92,10 @@ public class FileImportCache { } public Iterator readCache() throws IOException { + return readCache(true); + } + + public Iterator readCache(final boolean deleteAfterRead) throws IOException { File cacheDir = mContext.getCacheDir(); if (cacheDir == null) { @@ -166,7 +170,10 @@ public class FileImportCache { if (!closed) { try { ois.close(); - tempFile.delete(); + if (deleteAfterRead) { + //noinspection ResultOfMethodCallIgnored + tempFile.delete(); + } } catch (IOException e) { // nvm } @@ -177,4 +184,17 @@ public class FileImportCache { }; } + + public boolean delete() throws IOException { + + File cacheDir = mContext.getCacheDir(); + if (cacheDir == null) { + // https://groups.google.com/forum/#!topic/android-developers/-694j87eXVU + throw new IOException("cache dir is null!"); + } + + final File tempFile = new File(cacheDir, mFilename); + return tempFile.delete(); + } + } -- cgit v1.2.3 From a2ae318a1adb355efd593b8fd8041d75c25866b3 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 15:55:40 +0200 Subject: add OpenDialogActivity (stub) --- .../keychain/ui/OpenDialogActivity.java | 117 +++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java new file mode 100644 index 000000000..cdb09bbd0 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.ContextThemeWrapper; + +import org.sufficientlysecure.keychain.Constants; + +/** + * We can not directly create a dialog on the context provided inside the content provider. + * This activity encapsulates a DialogFragment to emulate a dialog. + */ +public class OpenDialogActivity extends FragmentActivity { + + public static final String EXTRA_MESSENGER = "messenger"; + public static final String EXTRA_FILENAME = "filename"; + + public static final int MSG_CANCEL = 1; + public static final int MSG_DECRYPT_OPEN = 2; + public static final int MSG_GET_ENCRYPTED = 3; + + MyDialogFragment mDialogFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // this activity itself has no content view (see manifest) + + mDialogFragment = new MyDialogFragment(); + // give all extras through to the fragment + mDialogFragment.setArguments(getIntent().getExtras()); + + mDialogFragment.show(getFragmentManager(), "dialog"); + } + + public static class MyDialogFragment extends DialogFragment { + + private Messenger mMessenger; + + /** + * Creates dialog + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + mMessenger = getArguments().getParcelable(EXTRA_MESSENGER); + String filename = getArguments().getString(EXTRA_FILENAME); + + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), + android.R.style.Theme_DeviceDefault_Light_Dialog); + ProgressDialog.Builder progress = new ProgressDialog.Builder(context); + return progress.show(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + dismiss(); + sendMessageToHandler(MSG_CANCEL); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + Log.d(Constants.TAG, "onDismiss"); + + getActivity().finish(); + } + + /** + * Send message back to handler which is initialized in a activity + * + * @param what Message integer you want to send + */ + private void sendMessageToHandler(Integer what) { + Message msg = Message.obtain(); + msg.what = what; + + try { + mMessenger.send(msg); + } catch (RemoteException e) { + Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); + } catch (NullPointerException e) { + Log.w(Constants.TAG, "Messenger is null!", e); + } + } + + } + +} -- cgit v1.2.3 From 0422d48b61011ff75ef6d85a6e45b90aebb5e58b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 15:55:53 +0200 Subject: add ProgressFixedScaler (forgot in a previous commit) --- .../keychain/util/ProgressFixedScaler.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java new file mode 100644 index 000000000..4bb4ca5de --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java @@ -0,0 +1,29 @@ +package org.sufficientlysecure.keychain.util; + +import org.sufficientlysecure.keychain.pgp.Progressable; + +/** This is a simple variant of ProgressScaler which shows a fixed progress message, ignoring + * the provided ones. + */ +public class ProgressFixedScaler extends ProgressScaler { + + final int mResId; + + public ProgressFixedScaler(Progressable wrapped, int from, int to, int max, int resId) { + super(wrapped, from, to, max); + mResId = resId; + } + + public void setProgress(int resourceId, int progress, int max) { + if (mWrapped != null) { + mWrapped.setProgress(mResId, mFrom + progress * (mTo - mFrom) / max, mMax); + } + } + + public void setProgress(String message, int progress, int max) { + if (mWrapped != null) { + mWrapped.setProgress(mResId, mFrom + progress * (mTo - mFrom) / max, mMax); + } + } + +} -- cgit v1.2.3 From 9fb1050fed5cdaa238219b29958cba1c484dff7e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 15:56:53 +0200 Subject: stub for consolidate recovery in KeychainApplication --- .../org/sufficientlysecure/keychain/KeychainApplication.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 9b9880533..233226cc5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -84,11 +84,18 @@ public class KeychainApplication extends Application { setupAccountAsNeeded(this); // Update keyserver list as needed - Preferences.getPreferences(this).updatePreferences(); + Preferences prefs = Preferences.getPreferences(this); + + prefs.updatePreferences(); TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); TemporaryStorageProvider.cleanUp(this); + + if (prefs.getCachedConsolidate()) { + // do something which calls ProviderHelper.consolidateDatabaseStep2 with a progressable + } + } public static void setupAccountAsNeeded(Context context) { -- cgit v1.2.3 From 5f8bbab5694bfe1e1c45205b075481d696f34738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 16:31:51 +0200 Subject: Scroll fixes for certify activity --- .../sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- .../keychain/ui/CertifyKeyActivity.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index b4e21cc0e..e357db412 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -930,7 +930,7 @@ public class PgpKeyOperation { hashedPacketsGen.setPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS); hashedPacketsGen.setPrimaryUserID(false, primary); - /* critical subpackets: */ + /* critical subpackets: we consider those important for a modern pgp implementation */ hashedPacketsGen.setSignatureCreationTime(true, new Date()); // Request that senders add the MDC to the message (authenticate unsigned messages) hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 7c6e94d5e..e81ebb9c4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -40,6 +40,7 @@ import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; import android.widget.ListView; +import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; @@ -71,6 +72,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag private ImageView mActionCertifyImage; private CheckBox mUploadKeyCheckbox; private Spinner mSelectKeyserverSpinner; + private ScrollView mScrollView; private CertifyKeySpinner mCertifyKeySpinner; @@ -96,6 +98,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag mCertifyButton = findViewById(R.id.certify_key_certify_button); mActionCertifyImage = (ImageView) findViewById(R.id.certify_key_action_certify_image); mUserIds = (ListView) findViewById(R.id.view_key_user_ids); + mScrollView = (ScrollView) findViewById(R.id.certify_scroll_view); // make certify image gray, like action icons mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light), @@ -141,6 +144,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag if (mMasterKeyId == 0) { Notify.showNotify(CertifyKeyActivity.this, getString(R.string.select_key_to_certify), Notify.Style.ERROR); + scrollUp(); } else { initiateCertifying(); } @@ -165,6 +169,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); } + private void scrollUp() { + mScrollView.post(new Runnable() { + public void run() { + mScrollView.fullScroll(ScrollView.FOCUS_UP); + } + }); + } + static final String USER_IDS_SELECTION = UserIds.IS_REVOKED + " = 0"; static final String[] KEYRING_PROJECTION = @@ -217,6 +229,9 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag break; case LOADER_ID_USER_IDS: mUserIdsAdapter.swapCursor(data); + // when some user ids are pre-checked, the focus is requested and the scroll view goes + // down. This fixes it. + scrollUp(); break; } } -- cgit v1.2.3 From 4f8ddad9d37f77d5a119623ccaf042f41b65ebbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 16:40:57 +0200 Subject: ConsolidateDialogActivity --- .../keychain/ui/ConsolidateDialogActivity.java | 102 ++++++++++++++++++ .../keychain/ui/OpenDialogActivity.java | 117 --------------------- 2 files changed, 102 insertions(+), 117 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java new file mode 100644 index 000000000..e4a80ff48 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.ContextThemeWrapper; +import android.view.KeyEvent; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; + +/** + * We can not directly create a dialog on the application context. + * This activity encapsulates a DialogFragment to emulate a dialog. + */ +public class ConsolidateDialogActivity extends FragmentActivity { + + MyDialogFragment mDialogFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // this activity itself has no content view (see manifest) + + mDialogFragment = new MyDialogFragment(); + // give all extras through to the fragment + mDialogFragment.setArguments(getIntent().getExtras()); + + mDialogFragment.show(getSupportFragmentManager(), "dialog"); + } + + public static class MyDialogFragment extends DialogFragment { + + /** + * Creates dialog + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), + R.style.Theme_AppCompat_Light); + ProgressDialog dialog = new ProgressDialog(context); + dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + + // Disable the back button + DialogInterface.OnKeyListener keyListener = new DialogInterface.OnKeyListener() { + @Override + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + return true; + } + return false; + } + + }; + dialog.setOnKeyListener(keyListener); + + return dialog; + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + dismiss(); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + Log.d(Constants.TAG, "onDismiss"); + + getActivity().finish(); + } + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java deleted file mode 100644 index cdb09bbd0..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OpenDialogActivity.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.ProgressDialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.FragmentActivity; -import android.util.Log; -import android.view.ContextThemeWrapper; - -import org.sufficientlysecure.keychain.Constants; - -/** - * We can not directly create a dialog on the context provided inside the content provider. - * This activity encapsulates a DialogFragment to emulate a dialog. - */ -public class OpenDialogActivity extends FragmentActivity { - - public static final String EXTRA_MESSENGER = "messenger"; - public static final String EXTRA_FILENAME = "filename"; - - public static final int MSG_CANCEL = 1; - public static final int MSG_DECRYPT_OPEN = 2; - public static final int MSG_GET_ENCRYPTED = 3; - - MyDialogFragment mDialogFragment; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // this activity itself has no content view (see manifest) - - mDialogFragment = new MyDialogFragment(); - // give all extras through to the fragment - mDialogFragment.setArguments(getIntent().getExtras()); - - mDialogFragment.show(getFragmentManager(), "dialog"); - } - - public static class MyDialogFragment extends DialogFragment { - - private Messenger mMessenger; - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - mMessenger = getArguments().getParcelable(EXTRA_MESSENGER); - String filename = getArguments().getString(EXTRA_FILENAME); - - // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay - ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), - android.R.style.Theme_DeviceDefault_Light_Dialog); - ProgressDialog.Builder progress = new ProgressDialog.Builder(context); - return progress.show(); - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - - dismiss(); - sendMessageToHandler(MSG_CANCEL); - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - Log.d(Constants.TAG, "onDismiss"); - - getActivity().finish(); - } - - /** - * Send message back to handler which is initialized in a activity - * - * @param what Message integer you want to send - */ - private void sendMessageToHandler(Integer what) { - Message msg = Message.obtain(); - msg.what = what; - - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } - - } - -} -- cgit v1.2.3 From c42f6a04eddf29eb655e56d574dee46374488614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 16:49:48 +0200 Subject: Start consolidate activity --- .../org/sufficientlysecure/keychain/KeychainApplication.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 233226cc5..bb691a9d2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -21,6 +21,7 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.app.Application; import android.content.Context; +import android.content.Intent; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Environment; @@ -29,6 +30,7 @@ import org.spongycastle.jce.provider.BouncyCastleProvider; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.TlsHelper; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; +import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PRNGFixes; @@ -92,12 +94,17 @@ public class KeychainApplication extends Application { TemporaryStorageProvider.cleanUp(this); + // restart consolidate process if it has been interruped before if (prefs.getCachedConsolidate()) { // do something which calls ProviderHelper.consolidateDatabaseStep2 with a progressable + Intent consolidateIntent = new Intent(this, ConsolidateDialogActivity.class); + consolidateIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(consolidateIntent); } - } + + public static void setupAccountAsNeeded(Context context) { AccountManager manager = AccountManager.get(context); Account[] accounts = manager.getAccountsByType(Constants.PACKAGE_NAME); -- cgit v1.2.3 From 9930ab7f6ff9400d6e3aa36ce06c663ce09be633 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 19 Aug 2014 16:53:44 +0200 Subject: consolidate: a lot more log output, better recovery --- .../keychain/helper/Preferences.java | 4 +- .../keychain/provider/ProviderHelper.java | 86 ++++++++++++++++------ .../keychain/service/OperationResultParcel.java | 25 +++++-- 3 files changed, 85 insertions(+), 30 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java index 9a10148f2..5190a550e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java @@ -146,7 +146,7 @@ public class Preferences { } public int getCachedConsolidateNumPublics() { - return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_PUBLICS, 100); + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_PUBLICS, -1); } public void setCachedConsolidateNumPublics(int value) { @@ -156,7 +156,7 @@ public class Preferences { } public int getCachedConsolidateNumSecrets() { - return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_SECRETS, 100); + return mSharedPreferences.getInt(Pref.CACHED_CONSOLIDATE_SECRETS, -1); } public void setCachedConsolidateNumSecrets(int value) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 5f55eedd5..4f8b50a94 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -829,12 +829,12 @@ public class ProviderHelper { public ConsolidateResult consolidateDatabaseStep1(Progressable progress) { // 1a. fetch all secret keyrings into a cache file - log(LogLevel.START, LogType.MSG_CON, mIndent); + log(LogLevel.START, LogType.MSG_CON); mIndent += 1; try { - log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_SECRET, mIndent); + log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_SECRET); mIndent += 1; final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ @@ -842,6 +842,7 @@ public class ProviderHelper { }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); if (cursor == null || !cursor.moveToFirst()) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_DB); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } @@ -883,7 +884,8 @@ public class ProviderHelper { }); } catch (IOException e) { - Log.e(Constants.TAG, "error saving secret"); + Log.e(Constants.TAG, "error saving secret", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_IO_SECRET); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } finally { mIndent -= 1; @@ -892,7 +894,7 @@ public class ProviderHelper { // 1b. fetch all public keyrings into a cache file try { - log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_PUBLIC, mIndent); + log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_PUBLIC); mIndent += 1; final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ @@ -900,10 +902,11 @@ public class ProviderHelper { }, null, null, null); if (cursor == null || !cursor.moveToFirst()) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_DB); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } - Preferences.getPreferences(mContext).setCachedConsolidateNumSecrets(cursor.getCount()); + Preferences.getPreferences(mContext).setCachedConsolidateNumPublics(cursor.getCount()); FileImportCache cache = new FileImportCache(mContext, "consolidate_public.pcl"); @@ -941,31 +944,48 @@ public class ProviderHelper { }); } catch (IOException e) { - Log.e(Constants.TAG, "error saving public"); + Log.e(Constants.TAG, "error saving public", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_IO_PUBLIC); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } finally { mIndent -= 1; } + log(LogLevel.INFO, LogType.MSG_CON_CRITICAL_IN); Preferences.getPreferences(mContext).setCachedConsolidate(true); - return consolidateDatabaseStep2(progress); + return consolidateDatabaseStep2(progress, false); } public ConsolidateResult consolidateDatabaseStep2(Progressable progress) { + return consolidateDatabaseStep2(progress, true); + } + + private ConsolidateResult consolidateDatabaseStep2(Progressable progress, boolean recovery) { + Preferences prefs = Preferences.getPreferences(mContext); - if ( ! prefs.getCachedConsolidate()) { - log(LogLevel.ERROR, LogType.MSG_CON_ERROR_BAD_STATE); - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } // Set flag that we have a cached consolidation here int numSecrets = prefs.getCachedConsolidateNumSecrets(); int numPublics = prefs.getCachedConsolidateNumPublics(); + if (recovery) { + if (numSecrets >= 0 && numPublics >= 0) { + log(LogLevel.START, LogType.MSG_CON_RECOVER, numSecrets, Integer.toString(numPublics)); + } else { + log(LogLevel.START, LogType.MSG_CON_RECOVER_UNKNOWN); + } + mIndent += 1; + } + + if ( ! prefs.getCachedConsolidate()) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_BAD_STATE); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + // 2. wipe database (IT'S DANGEROUS) - log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR, mIndent); + log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); new KeychainDatabase(mContext).clearDatabase(); FileImportCache cacheSecret = @@ -974,51 +994,71 @@ public class ProviderHelper { new FileImportCache(mContext, "consolidate_public.pcl"); // 3. Re-Import secret keyrings from cache - try { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, mIndent, numSecrets); + if (numSecrets > 0) try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, numSecrets); mIndent += 1; - new PgpImportExport(mContext, this, new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) + new PgpImportExport(mContext, this, + new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) .importKeyRings(cacheSecret.readCache(false), numSecrets); } catch (IOException e) { - Log.e(Constants.TAG, "error importing secret"); + Log.e(Constants.TAG, "error importing secret", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_SECRET); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } finally { mIndent -= 1; + } else { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET_SKIP); } // 4. Re-Import public keyrings from cache - try { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, mIndent, numPublics); + if (numPublics > 0) try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, numPublics); mIndent += 1; - new PgpImportExport(mContext, this, new ProgressScaler(progress, 25, 99, 100)) + new PgpImportExport(mContext, this, + new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport)) .importKeyRings(cachePublic.readCache(false), numPublics); } catch (IOException e) { - Log.e(Constants.TAG, "error importing public"); + Log.e(Constants.TAG, "error importing public", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_PUBLIC); return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); } finally { mIndent -= 1; + } else { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC_SKIP); } + log(LogLevel.INFO, LogType.MSG_CON_CRITICAL_OUT); Preferences.getPreferences(mContext).setCachedConsolidate(false); // 5. Delete caches try { + log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_SECRET); + mIndent += 1; cacheSecret.delete(); } catch (IOException e) { - // doesn't really matter + // doesn't /really/ matter Log.e(Constants.TAG, "IOException during delete of secret cache", e); + log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_SECRET); + } finally { + mIndent -= 1; } + try { + log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_PUBLIC); + mIndent += 1; cachePublic.delete(); } catch (IOException e) { - // doesn't really matter + // doesn't /really/ matter Log.e(Constants.TAG, "IOException during deletion of public cache", e); + log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_PUBLIC); + } finally { + mIndent -= 1; } progress.setProgress(100, 100); - log(LogLevel.OK, LogType.MSG_CON_SUCCESS, mIndent); + log(LogLevel.OK, LogType.MSG_CON_SUCCESS); mIndent -= 1; return new ConsolidateResult(ConsolidateResult.RESULT_OK, mLog); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 3f478cfed..cf9f69033 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -390,14 +390,29 @@ public class OperationResultParcel implements Parcelable { MSG_MF_UNLOCK (R.string.msg_mf_unlock), // consolidate - MSG_CON (R.string.msg_con), + MSG_CON_CRITICAL_IN (R.string.msg_con_critical_in), + MSG_CON_CRITICAL_OUT (R.string.msg_con_critical_out), + MSG_CON_DB_CLEAR (R.string.msg_con_db_clear), + MSG_CON_DELETE_PUBLIC (R.string.msg_con_delete_public), + MSG_CON_DELETE_SECRET (R.string.msg_con_delete_secret), MSG_CON_ERROR_BAD_STATE (R.string.msg_con_error_bad_state), - MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret), + MSG_CON_ERROR_DB (R.string.msg_con_error_db), + MSG_CON_ERROR_IO_PUBLIC (R.string.msg_con_error_io_public), + MSG_CON_ERROR_IO_SECRET (R.string.msg_con_error_io_secret), + MSG_CON_ERROR_PUBLIC (R.string.msg_con_error_public), + MSG_CON_ERROR_SECRET (R.string.msg_con_error_secret), + MSG_CON_RECOVER (R.plurals.msg_con_recover), + MSG_CON_RECOVER_UNKNOWN (R.string.msg_con_recover_unknown), + MSG_CON_REIMPORT_PUBLIC (R.string.msg_con_reimport_public), + MSG_CON_REIMPORT_PUBLIC_SKIP (R.string.msg_con_reimport_public_skip), + MSG_CON_REIMPORT_SECRET (R.string.msg_con_reimport_secret), + MSG_CON_REIMPORT_SECRET_SKIP (R.string.msg_con_reimport_secret_skip), + MSG_CON (R.string.msg_con), MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public), - MSG_CON_DB_CLEAR (R.string.msg_con_db_clear), - MSG_CON_REIMPORT_SECRET (R.plurals.msg_con_reimport_secret), - MSG_CON_REIMPORT_PUBLIC (R.plurals.msg_con_reimport_public), + MSG_CON_SAVE_SECRET (R.string.msg_con_save_secret), MSG_CON_SUCCESS (R.string.msg_con_success), + MSG_CON_WARN_DELETE_PUBLIC (R.string.msg_con_warn_delete_public), + MSG_CON_WARN_DELETE_SECRET (R.string.msg_con_warn_delete_secret), ; private final int mMsgId; -- cgit v1.2.3 From 16ab7610061726110f917533348f4c37a0690321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 19 Aug 2014 18:12:19 +0200 Subject: Fix strings --- .../java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 2 +- .../sufficientlysecure/keychain/service/OperationResultParcel.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 4f8b50a94..2867967ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -972,7 +972,7 @@ public class ProviderHelper { if (recovery) { if (numSecrets >= 0 && numPublics >= 0) { - log(LogLevel.START, LogType.MSG_CON_RECOVER, numSecrets, Integer.toString(numPublics)); + log(LogLevel.START, LogType.MSG_CON_RECOVER, numSecrets, numPublics); } else { log(LogLevel.START, LogType.MSG_CON_RECOVER_UNKNOWN); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index cf9f69033..91939739a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -403,9 +403,9 @@ public class OperationResultParcel implements Parcelable { MSG_CON_ERROR_SECRET (R.string.msg_con_error_secret), MSG_CON_RECOVER (R.plurals.msg_con_recover), MSG_CON_RECOVER_UNKNOWN (R.string.msg_con_recover_unknown), - MSG_CON_REIMPORT_PUBLIC (R.string.msg_con_reimport_public), + MSG_CON_REIMPORT_PUBLIC (R.plurals.msg_con_reimport_public), MSG_CON_REIMPORT_PUBLIC_SKIP (R.string.msg_con_reimport_public_skip), - MSG_CON_REIMPORT_SECRET (R.string.msg_con_reimport_secret), + MSG_CON_REIMPORT_SECRET (R.plurals.msg_con_reimport_secret), MSG_CON_REIMPORT_SECRET_SKIP (R.string.msg_con_reimport_secret_skip), MSG_CON (R.string.msg_con), MSG_CON_SAVE_PUBLIC (R.string.msg_con_save_public), -- cgit v1.2.3 From 1a6734f29c0a07c58f356e3861530adfe63f684a Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Tue, 19 Aug 2014 18:54:48 +0200 Subject: Fix mime types, #781 --- .../main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 59a433af3..d33e5116c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -382,7 +382,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris); } - sendIntent.setType("application/pgp-encrypted"); + sendIntent.setType("application/octet-stream"); } if (!isModeSymmetric() && mEncryptionUserIds != null) { Set users = new HashSet(); -- cgit v1.2.3 From 9aaaac068efa21c4f9fdc8ae9c79abdee685b0fc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 19:31:51 +0200 Subject: consolidate: use KeychainProvider for deletion operation --- .../java/org/sufficientlysecure/keychain/KeychainApplication.java | 2 -- .../org/sufficientlysecure/keychain/provider/KeychainDatabase.java | 2 +- .../org/sufficientlysecure/keychain/provider/KeychainProvider.java | 5 +++++ .../org/sufficientlysecure/keychain/provider/ProviderHelper.java | 3 +-- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index bb691a9d2..964a15d58 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -103,8 +103,6 @@ public class KeychainApplication extends Application { } } - - public static void setupAccountAsNeeded(Context context) { AccountManager manager = AccountManager.get(context); Account[] accounts = manager.getAccountsByType(Constants.PACKAGE_NAME); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 560eb9ef8..041c4d904 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -349,7 +349,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { copy(in, out); } - // DANGEROUS + // DANGEROUS, use in test code ONLY! public void clearDatabase() { getWritableDatabase().execSQL("delete from " + Tables.KEY_RINGS_PUBLIC); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 2c552a060..c5bf12143 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -685,6 +685,11 @@ public class KeychainProvider extends ContentProvider { final int match = mUriMatcher.match(uri); switch (match) { + // dangerous + case KEY_RINGS_UNIFIED: { + count = db.delete(Tables.KEY_RINGS_PUBLIC, null, null); + break; + } case KEY_RING_PUBLIC: { @SuppressWarnings("ConstantConditions") // ensured by uriMatcher above String selection = KeyRings.MASTER_KEY_ID + " = " + uri.getPathSegments().get(1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 2867967ff..daa920f74 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -963,7 +963,6 @@ public class ProviderHelper { private ConsolidateResult consolidateDatabaseStep2(Progressable progress, boolean recovery) { - Preferences prefs = Preferences.getPreferences(mContext); // Set flag that we have a cached consolidation here @@ -986,7 +985,7 @@ public class ProviderHelper { // 2. wipe database (IT'S DANGEROUS) log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); - new KeychainDatabase(mContext).clearDatabase(); + mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); FileImportCache cacheSecret = new FileImportCache(mContext, "consolidate_secret.pcl"); -- cgit v1.2.3 From fe1f5489ff8e819c8711f9bde3a19573bc621110 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 19:34:36 +0200 Subject: consolidate: implement (mostly) recovery mode --- .../keychain/provider/ProviderHelper.java | 5 ++ .../keychain/service/KeychainIntentService.java | 13 ++- .../keychain/ui/ConsolidateDialogActivity.java | 93 ++++++++++++---------- .../keychain/ui/KeyListActivity.java | 3 +- 4 files changed, 66 insertions(+), 48 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index daa920f74..125f33ded 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -987,6 +987,11 @@ public class ProviderHelper { log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); + // debug: break if this isn't recovery + if (!recovery) { + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + FileImportCache cacheSecret = new FileImportCache(mContext, "consolidate_secret.pcl"); FileImportCache cachePublic = diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2c1bc8463..ae881769d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -167,6 +167,10 @@ public class KeychainIntentService extends IntentService public static final String CERTIFY_KEY_PUB_KEY_ID = "sign_key_pub_key_id"; public static final String CERTIFY_KEY_UIDS = "sign_key_uids"; + // consolidate + public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery"; + + /* * possible data keys as result send over messenger */ @@ -183,8 +187,6 @@ public class KeychainIntentService extends IntentService public static final String RESULT_IMPORT = "result"; - public static final String RESULT_CONSOLIDATE = "consolidate_result"; - Messenger mMessenger; private boolean mIsCanceled; @@ -667,7 +669,12 @@ public class KeychainIntentService extends IntentService } } else if (ACTION_CONSOLIDATE.equals(action)) { - ConsolidateResult result = new ProviderHelper(this).consolidateDatabaseStep1(this); + ConsolidateResult result; + if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) { + result = new ProviderHelper(this).consolidateDatabaseStep2(this); + } else { + result = new ProviderHelper(this).consolidateDatabaseStep1(this); + } sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java index e4a80ff48..b21b1375e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java @@ -20,7 +20,10 @@ package org.sufficientlysecure.keychain.ui; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.util.Log; @@ -29,6 +32,9 @@ import android.view.KeyEvent; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; /** * We can not directly create a dialog on the application context. @@ -36,66 +42,65 @@ import org.sufficientlysecure.keychain.R; */ public class ConsolidateDialogActivity extends FragmentActivity { - MyDialogFragment mDialogFragment; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // this activity itself has no content view (see manifest) - mDialogFragment = new MyDialogFragment(); - // give all extras through to the fragment - mDialogFragment.setArguments(getIntent().getExtras()); + consolidateRecovery(); - mDialogFragment.show(getSupportFragmentManager(), "dialog"); } - public static class MyDialogFragment extends DialogFragment { - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay - ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), - R.style.Theme_AppCompat_Light); - ProgressDialog dialog = new ProgressDialog(context); - dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - dialog.setCancelable(false); - dialog.setCanceledOnTouchOutside(false); - - // Disable the back button - DialogInterface.OnKeyListener keyListener = new DialogInterface.OnKeyListener() { - @Override - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - return true; + private void consolidateRecovery() { + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + this, + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + /* don't care about the results (for now?) + + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; } - return false; - } + final ConsolidateResult result = + returnData.getParcelable(KeychainIntentService.RESULT_CONSOLIDATE); + if (result == null) { + return; + } + result.createNotify(ConsolidateDialogActivity.this).show(); + */ - }; - dialog.setOnKeyListener(keyListener); + ConsolidateDialogActivity.this.finish(); + } + } + }; - return dialog; - } + // Send all information needed to service to import key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + intent.setAction(KeychainIntentService.ACTION_CONSOLIDATE); - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); + // fill values for this action + Bundle data = new Bundle(); + data.putBoolean(KeychainIntentService.CONSOLIDATE_RECOVERY, true); + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - dismiss(); - } + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - Log.d(Constants.TAG, "onDismiss"); + // show progress dialog + saveHandler.showProgressDialog(this); - getActivity().finish(); - } + // start service with intent + startService(intent); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 9d9462648..0bc98d545 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -164,7 +165,7 @@ public class KeyListActivity extends DrawerActivity { return; } final ConsolidateResult result = - returnData.getParcelable(KeychainIntentService.RESULT_CONSOLIDATE); + returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); if (result == null) { return; } -- cgit v1.2.3 From f46f2b6895ac0c9c5c000e93457cb66049269ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 19:46:44 +0200 Subject: Fixes and temporary fixes for returning results --- .../keychain/remote/OpenPgpService.java | 4 ++-- .../keychain/service/KeychainIntentService.java | 2 -- .../keychain/service/OperationResultParcel.java | 4 +++- .../keychain/ui/CertifyKeyActivity.java | 24 ++++++++++++++-------- .../keychain/ui/ImportKeysActivity.java | 12 ++++++----- .../keychain/ui/LogDisplayFragment.java | 1 + 6 files changed, 29 insertions(+), 18 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index e2d809d9e..6e9f2fad6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -415,7 +415,7 @@ public class OpenPgpService extends RemoteService { // If signature is unknown we return an _additional_ PendingIntent // to retrieve the missing key Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE); intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, signatureResult.getKeyId()); intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data); @@ -481,7 +481,7 @@ public class OpenPgpService extends RemoteService { // If keys are not in db we return an additional PendingIntent // to retrieve the missing key Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE); intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, masterKeyId); intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2c1bc8463..99eab7f1d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -181,8 +181,6 @@ public class KeychainIntentService extends IntentService // export public static final String RESULT_EXPORT = "exported"; - public static final String RESULT_IMPORT = "result"; - public static final String RESULT_CONSOLIDATE = "consolidate_result"; Messenger mMessenger; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 91939739a..1ca06e6b6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -442,7 +442,9 @@ public class OperationResultParcel implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mResult); - dest.writeTypedList(mLog.toList()); + if (mLog != null) { + dest.writeTypedList(mLog.toList()); + } } public static final Creator CREATOR = new Creator() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index e81ebb9c4..323c6a00d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResultParcel; +import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; @@ -311,8 +312,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Notify.showNotify(CertifyKeyActivity.this, R.string.key_certify_success, - Notify.Style.INFO); +// Notify.showNotify(CertifyKeyActivity.this, R.string.key_certify_success, +// Notify.Style.INFO); + + OperationResultParcel result = new OperationResultParcel(OperationResultParcel.RESULT_OK, null); + Intent intent = new Intent(); + intent.putExtra(OperationResults.ImportKeyResult.EXTRA_RESULT, result); + CertifyKeyActivity.this.setResult(RESULT_OK, intent); + CertifyKeyActivity.this.finish(); // check if we need to send the key to the server or not if (mUploadKeyCheckbox.isChecked()) { @@ -364,13 +371,14 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Intent intent = new Intent(); - intent.putExtra(OperationResultParcel.EXTRA_RESULT, message.getData()); - Notify.showNotify(CertifyKeyActivity.this, R.string.key_send_success, - Notify.Style.INFO); + //Notify.showNotify(CertifyKeyActivity.this, R.string.key_send_success, + //Notify.Style.INFO); - setResult(RESULT_OK); - finish(); + OperationResultParcel result = new OperationResultParcel(OperationResultParcel.RESULT_OK, null); + Intent intent = new Intent(); + intent.putExtra(OperationResults.ImportKeyResult.EXTRA_RESULT, result); + CertifyKeyActivity.this.setResult(RESULT_OK, intent); + CertifyKeyActivity.this.finish(); } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 7df180296..0ec9b445b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; @@ -64,7 +65,7 @@ public class ImportKeysActivity extends ActionBarActivity { + "IMPORT_KEY_FROM_KEYSERVER"; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN_RESULT"; - public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN = Constants.INTENT_PREFIX + public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN"; public static final String ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_FILE_AND_RETURN"; @@ -87,7 +88,7 @@ public class ImportKeysActivity extends ActionBarActivity { public static final String EXTRA_KEY_ID = "key_id"; public static final String EXTRA_FINGERPRINT = "fingerprint"; - // only used by ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN when used from OpenPgpService + // only used by ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE when used from OpenPgpService public static final String EXTRA_PENDING_INTENT_DATA = "data"; private Intent mPendingIntentData; @@ -170,7 +171,7 @@ public class ImportKeysActivity extends ActionBarActivity { startListFragment(savedInstanceState, importData, null, null); } } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action) - || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(action) + || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(action) || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(action)) { // only used for OpenPgpService @@ -456,8 +457,9 @@ public class ImportKeysActivity extends ActionBarActivity { return; } final ImportKeyResult result = - returnData.getParcelable(KeychainIntentService.RESULT_IMPORT); + returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); if (result == null) { + Log.e(Constants.TAG, "result == null"); return; } @@ -468,7 +470,7 @@ public class ImportKeysActivity extends ActionBarActivity { ImportKeysActivity.this.finish(); return; } - if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) { + if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) { ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); ImportKeysActivity.this.finish(); return; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 0e948bf7f..7b0f3ecff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -179,6 +179,7 @@ public class LogDisplayFragment extends ListFragment implements OnTouchListener (Integer) entry.mParameters[0], entry.mParameters)); } else { + Log.d(Constants.TAG, "entry.mType.getMsgId() "+entry.mType.name()); ih.mText.setText(getResources().getString(entry.mType.getMsgId(), entry.mParameters)); } -- cgit v1.2.3 From 475293a116b5c3f7937bc5075921a2a0cb9c9a29 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 19:59:45 +0200 Subject: consolidate: prevent concurrent calls of step 2 --- .../keychain/KeychainApplication.java | 13 +- .../keychain/provider/ProviderHelper.java | 189 +++++++++++---------- .../keychain/service/OperationResultParcel.java | 1 + 3 files changed, 113 insertions(+), 90 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 964a15d58..ead29e229 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -86,21 +86,26 @@ public class KeychainApplication extends Application { setupAccountAsNeeded(this); // Update keyserver list as needed - Preferences prefs = Preferences.getPreferences(this); - - prefs.updatePreferences(); + Preferences.getPreferences(this).updatePreferences(); TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); TemporaryStorageProvider.cleanUp(this); + checkConsolidateRecovery(); + + } + + public void checkConsolidateRecovery() { + // restart consolidate process if it has been interruped before - if (prefs.getCachedConsolidate()) { + if (Preferences.getPreferences(this).getCachedConsolidate()) { // do something which calls ProviderHelper.consolidateDatabaseStep2 with a progressable Intent consolidateIntent = new Intent(this, ConsolidateDialogActivity.class); consolidateIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(consolidateIntent); } + } public static void setupAccountAsNeeded(Context context) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 125f33ded..0d6e83749 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -961,111 +961,128 @@ public class ProviderHelper { return consolidateDatabaseStep2(progress, true); } + private static boolean mConsolidateCritical = false; + private ConsolidateResult consolidateDatabaseStep2(Progressable progress, boolean recovery) { - Preferences prefs = Preferences.getPreferences(mContext); + synchronized (ProviderHelper.class) { + if (mConsolidateCritical) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_CONCURRENT); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } + mConsolidateCritical = true; + } - // Set flag that we have a cached consolidation here - int numSecrets = prefs.getCachedConsolidateNumSecrets(); - int numPublics = prefs.getCachedConsolidateNumPublics(); + try { + Preferences prefs = Preferences.getPreferences(mContext); - if (recovery) { - if (numSecrets >= 0 && numPublics >= 0) { - log(LogLevel.START, LogType.MSG_CON_RECOVER, numSecrets, numPublics); - } else { - log(LogLevel.START, LogType.MSG_CON_RECOVER_UNKNOWN); + // Set flag that we have a cached consolidation here + int numSecrets = prefs.getCachedConsolidateNumSecrets(); + int numPublics = prefs.getCachedConsolidateNumPublics(); + + if (recovery) { + if (numSecrets >= 0 && numPublics >= 0) { + log(LogLevel.START, LogType.MSG_CON_RECOVER, numSecrets, numPublics); + } else { + log(LogLevel.START, LogType.MSG_CON_RECOVER_UNKNOWN); + } + mIndent += 1; } - mIndent += 1; - } - if ( ! prefs.getCachedConsolidate()) { - log(LogLevel.ERROR, LogType.MSG_CON_ERROR_BAD_STATE); - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } + if (!prefs.getCachedConsolidate()) { + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_BAD_STATE); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } - // 2. wipe database (IT'S DANGEROUS) - log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); - mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); + // 2. wipe database (IT'S DANGEROUS) + log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); + mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); - // debug: break if this isn't recovery - if (!recovery) { - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } + // debug: break if this isn't recovery + if (!recovery) { + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } - FileImportCache cacheSecret = - new FileImportCache(mContext, "consolidate_secret.pcl"); - FileImportCache cachePublic = - new FileImportCache(mContext, "consolidate_public.pcl"); + FileImportCache cacheSecret = + new FileImportCache(mContext, "consolidate_secret.pcl"); + FileImportCache cachePublic = + new FileImportCache(mContext, "consolidate_public.pcl"); - // 3. Re-Import secret keyrings from cache - if (numSecrets > 0) try { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, numSecrets); - mIndent += 1; + // 3. Re-Import secret keyrings from cache + if (numSecrets > 0) try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET, numSecrets); + mIndent += 1; - new PgpImportExport(mContext, this, - new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) - .importKeyRings(cacheSecret.readCache(false), numSecrets); - } catch (IOException e) { - Log.e(Constants.TAG, "error importing secret", e); - log(LogLevel.ERROR, LogType.MSG_CON_ERROR_SECRET); - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } finally { - mIndent -= 1; - } else { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET_SKIP); - } + new PgpImportExport(mContext, this, + new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) + .importKeyRings(cacheSecret.readCache(false), numSecrets); + } catch (IOException e) { + Log.e(Constants.TAG, "error importing secret", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_SECRET); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + else { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_SECRET_SKIP); + } - // 4. Re-Import public keyrings from cache - if (numPublics > 0) try { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, numPublics); - mIndent += 1; + // 4. Re-Import public keyrings from cache + if (numPublics > 0) try { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC, numPublics); + mIndent += 1; - new PgpImportExport(mContext, this, - new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport)) - .importKeyRings(cachePublic.readCache(false), numPublics); - } catch (IOException e) { - Log.e(Constants.TAG, "error importing public", e); - log(LogLevel.ERROR, LogType.MSG_CON_ERROR_PUBLIC); - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } finally { - mIndent -= 1; - } else { - log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC_SKIP); - } + new PgpImportExport(mContext, this, + new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport)) + .importKeyRings(cachePublic.readCache(false), numPublics); + } catch (IOException e) { + Log.e(Constants.TAG, "error importing public", e); + log(LogLevel.ERROR, LogType.MSG_CON_ERROR_PUBLIC); + return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); + } finally { + mIndent -= 1; + } + else { + log(LogLevel.DEBUG, LogType.MSG_CON_REIMPORT_PUBLIC_SKIP); + } - log(LogLevel.INFO, LogType.MSG_CON_CRITICAL_OUT); - Preferences.getPreferences(mContext).setCachedConsolidate(false); + log(LogLevel.INFO, LogType.MSG_CON_CRITICAL_OUT); + Preferences.getPreferences(mContext).setCachedConsolidate(false); - // 5. Delete caches - try { - log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_SECRET); - mIndent += 1; - cacheSecret.delete(); - } catch (IOException e) { - // doesn't /really/ matter - Log.e(Constants.TAG, "IOException during delete of secret cache", e); - log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_SECRET); - } finally { - mIndent -= 1; - } + // 5. Delete caches + try { + log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_SECRET); + mIndent += 1; + cacheSecret.delete(); + } catch (IOException e) { + // doesn't /really/ matter + Log.e(Constants.TAG, "IOException during delete of secret cache", e); + log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_SECRET); + } finally { + mIndent -= 1; + } - try { - log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_PUBLIC); - mIndent += 1; - cachePublic.delete(); - } catch (IOException e) { - // doesn't /really/ matter - Log.e(Constants.TAG, "IOException during deletion of public cache", e); - log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_PUBLIC); - } finally { + try { + log(LogLevel.DEBUG, LogType.MSG_CON_DELETE_PUBLIC); + mIndent += 1; + cachePublic.delete(); + } catch (IOException e) { + // doesn't /really/ matter + Log.e(Constants.TAG, "IOException during deletion of public cache", e); + log(LogLevel.WARN, LogType.MSG_CON_WARN_DELETE_PUBLIC); + } finally { + mIndent -= 1; + } + + progress.setProgress(100, 100); + log(LogLevel.OK, LogType.MSG_CON_SUCCESS); mIndent -= 1; - } - progress.setProgress(100, 100); - log(LogLevel.OK, LogType.MSG_CON_SUCCESS); - mIndent -= 1; + return new ConsolidateResult(ConsolidateResult.RESULT_OK, mLog); - return new ConsolidateResult(ConsolidateResult.RESULT_OK, mLog); + } finally { + mConsolidateCritical = false; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 91939739a..7fe712534 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -396,6 +396,7 @@ public class OperationResultParcel implements Parcelable { MSG_CON_DELETE_PUBLIC (R.string.msg_con_delete_public), MSG_CON_DELETE_SECRET (R.string.msg_con_delete_secret), MSG_CON_ERROR_BAD_STATE (R.string.msg_con_error_bad_state), + MSG_CON_ERROR_CONCURRENT(R.string.msg_con_error_concurrent), MSG_CON_ERROR_DB (R.string.msg_con_error_db), MSG_CON_ERROR_IO_PUBLIC (R.string.msg_con_error_io_public), MSG_CON_ERROR_IO_SECRET (R.string.msg_con_error_io_secret), -- cgit v1.2.3 From 47bcc6149e72d4bc354e5065feefcedca6c7db26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 20:08:51 +0200 Subject: return some more results --- .../keychain/ui/CertifyKeyActivity.java | 4 +- .../keychain/ui/CreateKeyFinalFragment.java | 45 +++++++++------------- .../keychain/ui/FirstTimeActivity.java | 12 +++--- .../keychain/ui/KeyListActivity.java | 13 ++++++- .../keychain/ui/LogDisplayFragment.java | 1 - .../keychain/ui/ViewKeyActivity.java | 1 + 6 files changed, 41 insertions(+), 35 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 323c6a00d..728e6e1e1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -317,7 +317,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag OperationResultParcel result = new OperationResultParcel(OperationResultParcel.RESULT_OK, null); Intent intent = new Intent(); - intent.putExtra(OperationResults.ImportKeyResult.EXTRA_RESULT, result); + intent.putExtra(OperationResultParcel.EXTRA_RESULT, result); CertifyKeyActivity.this.setResult(RESULT_OK, intent); CertifyKeyActivity.this.finish(); @@ -376,7 +376,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements LoaderManag OperationResultParcel result = new OperationResultParcel(OperationResultParcel.RESULT_OK, null); Intent intent = new Intent(); - intent.putExtra(OperationResults.ImportKeyResult.EXTRA_RESULT, result); + intent.putExtra(OperationResultParcel.EXTRA_RESULT, result); CertifyKeyActivity.this.setResult(RESULT_OK, intent); CertifyKeyActivity.this.finish(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 22c0f7767..076f52a10 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -33,6 +33,7 @@ import android.widget.TextView; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.sig.KeyFlags; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.pgp.KeyRing; @@ -42,6 +43,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; public class CreateKeyFinalFragment extends Fragment { @@ -142,23 +144,18 @@ public class CreateKeyFinalFragment extends Fragment { final OperationResults.SaveKeyringResult result = returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); if (result == null) { + Log.e(Constants.TAG, "result == null"); return; } - if (result.getResult() == OperationResultParcel.RESULT_OK) { - if (mUploadCheckbox.isChecked()) { - // result will be displayed after upload - uploadKey(result); - } else { - // TODO: return result - result.createNotify(getActivity()); - - getActivity().setResult(Activity.RESULT_OK); - getActivity().finish(); - } + if (mUploadCheckbox.isChecked()) { + // result will be displayed after upload + uploadKey(result); } else { - // display result on error without finishing activity - result.createNotify(getActivity()); + Intent data = new Intent(); + data.putExtra(OperationResultParcel.EXTRA_RESULT, result); + getActivity().setResult(Activity.RESULT_OK, data); + getActivity().finish(); } } } @@ -217,20 +214,16 @@ public class CreateKeyFinalFragment extends Fragment { super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // TODO: not supported by upload? -// if (result.getResult() == OperationResultParcel.RESULT_OK) { - // TODO: return result - editKeyResult.createNotify(getActivity()); - - Notify.showNotify(getActivity(), R.string.key_send_success, - Notify.Style.INFO); - - getActivity().setResult(Activity.RESULT_OK); + // TODO: upload operation needs a result! + // TODO: then combine these results + //if (result.getResult() == OperationResultParcel.RESULT_OK) { + //Notify.showNotify(getActivity(), R.string.key_send_success, + //Notify.Style.INFO); + + Intent data = new Intent(); + data.putExtra(OperationResultParcel.EXTRA_RESULT, editKeyResult); + getActivity().setResult(Activity.RESULT_OK, data); getActivity().finish(); -// } else { -// // display result on error without finishing activity -// editKeyResult.createNotify(getActivity()); -// } } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java index 5f3f170a1..9811500a2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java @@ -51,7 +51,7 @@ public class FirstTimeActivity extends ActionBarActivity { mSkipSetup.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - finishSetup(); + finishSetup(null); } }); @@ -80,18 +80,20 @@ public class FirstTimeActivity extends ActionBarActivity { if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) { if (resultCode == RESULT_OK) { - finishSetup(); + finishSetup(data); } } else { Log.e(Constants.TAG, "No valid request code!"); } } - private void finishSetup() { + private void finishSetup(Intent srcData) { Preferences prefs = Preferences.getPreferences(this); prefs.setFirstTime(false); - Intent intent = new Intent(FirstTimeActivity.this, KeyListActivity.class); - startActivity(intent); + Intent intent = new Intent(this, KeyListActivity.class); + // give intent through to display notify + intent.putExtras(srcData); + startActivityForResult(intent, 0); finish(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 0bc98d545..7663b7366 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -145,7 +145,7 @@ public class KeyListActivity extends DrawerActivity { private void createKey() { Intent intent = new Intent(this, CreateKeyActivity.class); - startActivity(intent); + startActivityForResult(intent, 0); } private void consolidate() { @@ -197,4 +197,15 @@ public class KeyListActivity extends DrawerActivity { } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // if a result has been returned, display a notify + if (data != null && data.hasExtra(OperationResultParcel.EXTRA_RESULT)) { + OperationResultParcel result = data.getParcelableExtra(OperationResultParcel.EXTRA_RESULT); + result.createNotify(this).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 7b0f3ecff..0e948bf7f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -179,7 +179,6 @@ public class LogDisplayFragment extends ListFragment implements OnTouchListener (Integer) entry.mParameters[0], entry.mParameters)); } else { - Log.d(Constants.TAG, "entry.mType.getMsgId() "+entry.mType.name()); ih.mText.setText(getResources().getString(entry.mType.getMsgId(), entry.mParameters)); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 28f7b8bf5..c9db79740 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -313,6 +313,7 @@ public class ViewKeyActivity extends ActionBarActivity implements @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // if a result has been returned, display a notify if (data != null && data.hasExtra(OperationResultParcel.EXTRA_RESULT)) { OperationResultParcel result = data.getParcelableExtra(OperationResultParcel.EXTRA_RESULT); result.createNotify(this).show(); -- cgit v1.2.3 From 50c33ef3223c77ca8c36285ef379fd80ab2e77e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 20:13:25 +0200 Subject: progress dialog design fix --- .../sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java | 8 -------- .../keychain/ui/dialog/ProgressDialogFragment.java | 8 +++++++- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java index b21b1375e..edc05e28d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java @@ -17,24 +17,16 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Dialog; import android.app.ProgressDialog; -import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Message; import android.os.Messenger; -import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; -import android.util.Log; -import android.view.ContextThemeWrapper; -import android.view.KeyEvent; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.OperationResults.ConsolidateResult; /** * We can not directly create a dialog on the application context. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java index 093a04aff..0324dd3b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java @@ -25,6 +25,7 @@ import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnKeyListener; import android.os.Bundle; import android.support.v4.app.DialogFragment; +import android.view.ContextThemeWrapper; import android.view.KeyEvent; import org.sufficientlysecure.keychain.R; @@ -113,7 +114,12 @@ public class ProgressDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); - ProgressDialog dialog = new ProgressDialog(activity); + // if the progress dialog is displayed from the application class, design is missing + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper context = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light); + + ProgressDialog dialog = new ProgressDialog(context); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.setCanceledOnTouchOutside(false); -- cgit v1.2.3 From c2965290497e12d65d0a8412c8f29d7134a05c95 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 20:15:43 +0200 Subject: modifyKey: small logging changes --- .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index e357db412..f3af51397 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -690,7 +690,7 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, add.mKeysize, + log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, Integer.toString(add.mKeysize), PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm) ); if (add.mExpiry == null) { -- cgit v1.2.3 From 735040e19302a99587c5dfd058de7fd0f1db6ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 20:24:19 +0200 Subject: return some more results --- .../keychain/remote/ui/AccountSettingsActivity.java | 12 ++++++++++++ .../sufficientlysecure/keychain/ui/ImportKeysActivity.java | 8 ++------ 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java index 666252353..67ad0822d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java @@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.util.Log; public class AccountSettingsActivity extends ActionBarActivity { @@ -106,4 +107,15 @@ public class AccountSettingsActivity extends ActionBarActivity { finish(); } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // if a result has been returned, display a notify + if (data != null && data.hasExtra(OperationResultParcel.EXTRA_RESULT)) { + OperationResultParcel result = data.getParcelableExtra(OperationResultParcel.EXTRA_RESULT); + result.createNotify(this).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 0ec9b445b..18f805360 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -463,7 +463,8 @@ public class ImportKeysActivity extends ActionBarActivity { return; } - if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())) { + if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction()) + || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { Intent intent = new Intent(); intent.putExtra(ImportKeyResult.EXTRA_RESULT, result); ImportKeysActivity.this.setResult(RESULT_OK, intent); @@ -475,11 +476,6 @@ public class ImportKeysActivity extends ActionBarActivity { ImportKeysActivity.this.finish(); return; } - if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { - ImportKeysActivity.this.setResult(RESULT_OK); - ImportKeysActivity.this.finish(); - return; - } result.createNotify(ImportKeysActivity.this).show(); } -- cgit v1.2.3 From 937c91eefaa55ef5bc065b54a4ec9b04c8f3a522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 20:44:49 +0200 Subject: Fix nullpointer in first time activity --- .../java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java index 9811500a2..7b608a0a2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java @@ -92,7 +92,9 @@ public class FirstTimeActivity extends ActionBarActivity { prefs.setFirstTime(false); Intent intent = new Intent(this, KeyListActivity.class); // give intent through to display notify - intent.putExtras(srcData); + if (srcData != null) { + intent.putExtras(srcData); + } startActivityForResult(intent, 0); finish(); } -- cgit v1.2.3 From 45706e653466743dcfd5ac5bb150f5a7907d59f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 21:09:46 +0200 Subject: Notify duration, cleanup --- .../sufficientlysecure/keychain/service/OperationResultParcel.java | 7 ++----- .../java/org/sufficientlysecure/keychain/ui/KeyListFragment.java | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index a7092d7c7..3f48a2200 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -155,10 +155,8 @@ public class OperationResultParcel implements Parcelable { if ((resultType & OperationResultParcel.RESULT_ERROR) == 0) { if (getLog().containsWarnings()) { - duration = 0; color = Style.ORANGE; } else { - duration = SuperToast.Duration.LONG; color = Style.GREEN; } @@ -167,7 +165,6 @@ public class OperationResultParcel implements Parcelable { } else { - duration = 0; color = Style.RED; str = "operation failed"; @@ -180,8 +177,8 @@ public class OperationResultParcel implements Parcelable { button ? SuperToast.Type.BUTTON : SuperToast.Type.STANDARD, Style.getStyle(color, SuperToast.Animations.POPUP)); toast.setText(str); - toast.setDuration(duration); - toast.setIndeterminate(duration == 0); + toast.setDuration(SuperToast.Duration.EXTRA_LONG); + toast.setIndeterminate(false); toast.setSwipeToDismiss(true); // If we have a log and it's non-empty, show a View Log button if (button) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index e7b7d2efc..d1109631a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -85,8 +85,6 @@ public class KeyListFragment extends LoaderFragment private Button mButtonEmptyCreate; private Button mButtonEmptyImport; - public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012; - /** * Load custom layout with StickyListView from library */ @@ -105,7 +103,7 @@ public class KeyListFragment extends LoaderFragment @Override public void onClick(View v) { Intent intent = new Intent(getActivity(), CreateKeyActivity.class); - startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); + startActivityForResult(intent, 0); } }); mButtonEmptyImport = (Button) view.findViewById(R.id.key_list_empty_button_import); @@ -115,7 +113,7 @@ public class KeyListFragment extends LoaderFragment public void onClick(View v) { Intent intent = new Intent(getActivity(), ImportKeysActivity.class); intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); - startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); + startActivityForResult(intent, 0); } }); -- cgit v1.2.3 From 6ed0f667cd1d556a923bc7d624f296abe17f795a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 21:29:11 +0200 Subject: consolidate: remove debug "breakpoint" --- .../org/sufficientlysecure/keychain/provider/ProviderHelper.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 0d6e83749..47f4682c7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -998,11 +998,6 @@ public class ProviderHelper { log(LogLevel.DEBUG, LogType.MSG_CON_DB_CLEAR); mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); - // debug: break if this isn't recovery - if (!recovery) { - return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, mLog); - } - FileImportCache cacheSecret = new FileImportCache(mContext, "consolidate_secret.pcl"); FileImportCache cachePublic = -- cgit v1.2.3 From e33e5b0003614d27365c8b2f713ba2293b0c13d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 21:44:51 +0200 Subject: Work on upload key --- .../keychain/keyimport/HkpKeyserver.java | 38 ++++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index f617be62a..e63fdeb6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -24,8 +24,10 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.util.Log; -import java.io.DataOutputStream; +import java.io.BufferedWriter; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; @@ -352,24 +354,32 @@ public class HkpKeyserver extends Keyserver { @Override public void add(String armoredKey) throws AddKeyException { try { - String query = getUrlPrefix() + mHost + ":" + mPort + "/pks/add"; + String request = "/pks/add"; String params; try { - params = "keytext=" + URLEncoder.encode(armoredKey, "utf8"); + params = "keytext=" + URLEncoder.encode(armoredKey, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new AddKeyException(); } - Log.d(Constants.TAG, "hkp keyserver add: " + query); - - HttpURLConnection connection = openConnection(new URL(query)); - connection.setRequestMethod("POST"); - connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - connection.setRequestProperty("Content-Length", Integer.toString(params.getBytes().length)); - connection.setDoOutput(true); - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); - wr.writeBytes(params); - wr.flush(); - wr.close(); + URL url = new URL(getUrlPrefix() + mHost + ":" + mPort + request); + + Log.d(Constants.TAG, "hkp keyserver add: " + url.toString()); + + HttpURLConnection conn = openConnection(url); + conn.setRequestMethod("POST"); + conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.setRequestProperty("Content-Length", Integer.toString(params.getBytes().length)); + conn.setDoInput(true); + conn.setDoOutput(true); + + OutputStream os = conn.getOutputStream(); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); + writer.write(params); + writer.flush(); + writer.close(); + os.close(); + + conn.connect(); } catch (IOException e) { throw new AddKeyException(); } -- cgit v1.2.3 From fa25265e7967b29c6ab9a2ecec97b0d076261f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 21:51:01 +0200 Subject: Fix key sharing --- .../java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 0d6e83749..8fd4bc7cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1128,9 +1128,7 @@ public class ProviderHelper { ByteArrayOutputStream bos = new ByteArrayOutputStream(); String version = PgpHelper.getVersionForHeader(mContext); - if (version != null) { - keyRing.encodeArmored(bos, version); - } + keyRing.encodeArmored(bos, version); String armoredKey = bos.toString("UTF-8"); Log.d(Constants.TAG, "armoredKey:" + armoredKey); -- cgit v1.2.3 From 9122d43d0ab681cfafa67a0b8f81e07776f86083 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 21:51:19 +0200 Subject: close actionmode in keylist on loading events (avoid inconsistent state) --- .../org/sufficientlysecure/keychain/ui/KeyListFragment.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index e7b7d2efc..d50ff4331 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -79,6 +79,9 @@ public class KeyListFragment extends LoaderFragment private KeyListAdapter mAdapter; private StickyListHeadersListView mStickyList; + // saves the mode object for multiselect, needed for reset at some point + private ActionMode mActionMode = null; + private String mQuery; private SearchView mSearchView; // empty list layout @@ -148,6 +151,7 @@ public class KeyListFragment extends LoaderFragment public boolean onCreateActionMode(ActionMode mode, Menu menu) { android.view.MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.key_list_multi, menu); + mActionMode = mode; return true; } @@ -193,6 +197,7 @@ public class KeyListFragment extends LoaderFragment @Override public void onDestroyActionMode(ActionMode mode) { + mActionMode = null; mAdapter.clearSelection(); } @@ -288,6 +293,11 @@ public class KeyListFragment extends LoaderFragment // this view is made visible if no data is available mStickyList.setEmptyView(getActivity().findViewById(R.id.key_list_empty)); + // end action mode, if any + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && mActionMode != null) { + mActionMode.finish(); + } + // The list should now be shown. if (isResumed()) { setContentShown(true); -- cgit v1.2.3 From 6c428fa6b58fcaa8f681baa9ec5b98625c9cef91 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 21:51:57 +0200 Subject: make number of secret keys imported part of ImportResult parcel --- .../org/sufficientlysecure/keychain/pgp/PgpImportExport.java | 9 ++++++--- .../sufficientlysecure/keychain/service/OperationResults.java | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index fd37112a5..94ff4a1ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -139,10 +139,10 @@ public class PgpImportExport { // If there aren't even any keys, do nothing here. if (entries == null || !entries.hasNext()) { return new ImportKeyResult( - ImportKeyResult.RESULT_FAIL_NOTHING, mProviderHelper.getLog(), 0, 0, 0); + ImportKeyResult.RESULT_FAIL_NOTHING, mProviderHelper.getLog(), 0, 0, 0, 0); } - int newKeys = 0, oldKeys = 0, badKeys = 0; + int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0; int position = 0; double progSteps = 100.0 / num; @@ -177,6 +177,9 @@ public class PgpImportExport { oldKeys += 1; } else { newKeys += 1; + if (key.isSecret()) { + secret += 1; + } } } catch (IOException e) { @@ -213,7 +216,7 @@ public class PgpImportExport { } } - return new ImportKeyResult(resultType, log, newKeys, oldKeys, badKeys); + return new ImportKeyResult(resultType, log, newKeys, oldKeys, badKeys, secret); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index 878f6ca47..c59a7d172 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -40,7 +40,7 @@ public abstract class OperationResults { public static class ImportKeyResult extends OperationResultParcel { - public final int mNewKeys, mUpdatedKeys, mBadKeys; + public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret; // At least one new key public static final int RESULT_OK_NEWKEYS = 2; @@ -76,14 +76,16 @@ public abstract class OperationResults { mNewKeys = source.readInt(); mUpdatedKeys = source.readInt(); mBadKeys = source.readInt(); + mSecret = source.readInt(); } public ImportKeyResult(int result, OperationLog log, - int newKeys, int updatedKeys, int badKeys) { + int newKeys, int updatedKeys, int badKeys, int secret) { super(result, log); mNewKeys = newKeys; mUpdatedKeys = updatedKeys; mBadKeys = badKeys; + mSecret = secret; } @Override @@ -92,6 +94,7 @@ public abstract class OperationResults { dest.writeInt(mNewKeys); dest.writeInt(mUpdatedKeys); dest.writeInt(mBadKeys); + dest.writeInt(mSecret); } public static Creator CREATOR = new Creator() { -- cgit v1.2.3 From dd1b27b28f7c84cc10a4dd632b2175d9171f6c72 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 21:52:54 +0200 Subject: consolidate: small ui things --- .../java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 47f4682c7..717d3c5ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -832,6 +832,8 @@ public class ProviderHelper { log(LogLevel.START, LogType.MSG_CON); mIndent += 1; + progress.setProgress(R.string.progress_con_saving, 0, 100); + try { log(LogLevel.DEBUG, LogType.MSG_CON_SAVE_SECRET); @@ -891,6 +893,8 @@ public class ProviderHelper { mIndent -= 1; } + progress.setProgress(R.string.progress_con_saving, 3, 100); + // 1b. fetch all public keyrings into a cache file try { -- cgit v1.2.3 From 0f8958afb91c1b28a3509c91d0a7b7b56b9b6343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 22:17:16 +0200 Subject: Upload key working --- .../java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index e63fdeb6d..2fe32dc6b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -380,6 +380,9 @@ public class HkpKeyserver extends Keyserver { os.close(); conn.connect(); + + Log.d(Constants.TAG, "response code: " + conn.getResponseCode()); + Log.d(Constants.TAG, "answer: " + readAll(conn.getInputStream(), conn.getContentEncoding())); } catch (IOException e) { throw new AddKeyException(); } -- cgit v1.2.3 From 37caddca7021039f9828d1c08164499748fb5ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 22:51:00 +0200 Subject: Upload key working --- .../sufficientlysecure/keychain/keyimport/HkpKeyserver.java | 2 ++ .../keychain/pgp/CanonicalizedPublicKeyRing.java | 4 ---- .../org/sufficientlysecure/keychain/pgp/PgpImportExport.java | 10 +++------- .../keychain/service/KeychainIntentService.java | 5 +++-- 4 files changed, 8 insertions(+), 13 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 2fe32dc6b..69ac2551f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -364,6 +364,7 @@ public class HkpKeyserver extends Keyserver { URL url = new URL(getUrlPrefix() + mHost + ":" + mPort + request); Log.d(Constants.TAG, "hkp keyserver add: " + url.toString()); + Log.d(Constants.TAG, "params: " + params); HttpURLConnection conn = openConnection(url); conn.setRequestMethod("POST"); @@ -384,6 +385,7 @@ public class HkpKeyserver extends Keyserver { Log.d(Constants.TAG, "response code: " + conn.getResponseCode()); Log.d(Constants.TAG, "answer: " + readAll(conn.getInputStream(), conn.getContentEncoding())); } catch (IOException e) { + Log.e(Constants.TAG, "IOException", e); throw new AddKeyException(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java index 972e45c2e..7b5d5d4be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java @@ -60,10 +60,6 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing { return mRing; } - public void encode(ArmoredOutputStream stream) throws IOException { - getRing().encode(stream); - } - /** Getter that returns the subkey that should be used for signing. */ CanonicalizedPublicKey getEncryptionSubKey() throws PgpGeneralException { PGPPublicKey key = getRing().getPublicKey(getEncryptId()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index fd37112a5..067af3f7c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -99,7 +99,7 @@ public class PgpImportExport { } } - public boolean uploadKeyRingToServer(HkpKeyserver server, CanonicalizedPublicKeyRing keyring) { + public void uploadKeyRingToServer(HkpKeyserver server, CanonicalizedPublicKeyRing keyring) throws AddKeyException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ArmoredOutputStream aos = null; try { @@ -109,13 +109,9 @@ public class PgpImportExport { String armoredKey = bos.toString("UTF-8"); server.add(armoredKey); - - return true; } catch (IOException e) { - return false; - } catch (AddKeyException e) { - // TODO: tell the user? - return false; + Log.e(Constants.TAG, "IOException", e); + throw new AddKeyException(); } finally { try { if (aos != null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d568df91a..e82c43d82 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -575,8 +575,9 @@ public class KeychainIntentService extends IntentService CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri); PgpImportExport pgpImportExport = new PgpImportExport(this, null); - boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, keyring); - if (!uploaded) { + try { + pgpImportExport.uploadKeyRingToServer(server, keyring); + } catch (Keyserver.AddKeyException e) { throw new PgpGeneralException("Unable to export key to selected server"); } -- cgit v1.2.3 From dcf268bcb2cbe433fdef8af4fd516a6482ac268a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 23:08:52 +0200 Subject: move key deletion into KeychainIntentHandler --- .../keychain/service/KeychainIntentService.java | 50 ++++++++++++- .../keychain/ui/ViewKeyActivity.java | 8 +- .../ui/dialog/DeleteKeyDialogFragment.java | 85 ++++++++++++---------- 3 files changed, 103 insertions(+), 40 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d568df91a..4330a1c01 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -49,6 +49,7 @@ import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -104,6 +105,8 @@ public class KeychainIntentService extends IntentService public static final String ACTION_CERTIFY_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; + public static final String ACTION_DELETE = Constants.INTENT_PREFIX + "DELETE"; + public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE"; /* keys for data bundle */ @@ -143,6 +146,10 @@ public class KeychainIntentService extends IntentService // delete file securely public static final String DELETE_FILE = "deleteFile"; + // delete keyring(s) + public static final String DELETE_KEY_LIST = "delete_list"; + public static final String DELETE_IS_SECRET = "delete_is_secret"; + // import key public static final String IMPORT_KEY_LIST = "import_key_list"; public static final String IMPORT_KEY_FILE = "import_key_file"; @@ -487,9 +494,14 @@ public class KeychainIntentService extends IntentService entries = cache.readCacheIntoList(); } - PgpImportExport pgpImportExport = new PgpImportExport(this, this); + ProviderHelper providerHelper = new ProviderHelper(this); + PgpImportExport pgpImportExport = new PgpImportExport(this, providerHelper, this); ImportKeyResult result = pgpImportExport.importKeyRings(entries); + if (result.mSecret > 0) { + providerHelper.consolidateDatabaseStep1(this); + } + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } catch (Exception e) { sendErrorToHandler(e); @@ -666,6 +678,42 @@ public class KeychainIntentService extends IntentService sendErrorToHandler(e); } + } else if (ACTION_DELETE.equals(action)) { + + try { + + long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST); + boolean isSecret = data.getBoolean(DELETE_IS_SECRET); + + if (masterKeyIds.length == 0) { + throw new PgpGeneralException("List of keys to delete is empty"); + } + + if (isSecret && masterKeyIds.length > 1) { + throw new PgpGeneralException("Secret keys can only be deleted individually!"); + } + + boolean success = false; + for (long masterKeyId : masterKeyIds) { + int count = getContentResolver().delete( + KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null + ); + success |= count > 0; + } + + if (isSecret && success) { + ConsolidateResult result = + new ProviderHelper(this).consolidateDatabaseStep1(this); + } + + if (success) { + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); + } + + } catch (Exception e) { + sendErrorToHandler(e); + } + } else if (ACTION_CONSOLIDATE.equals(action)) { ConsolidateResult result; if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index c9db79740..2c0881ea4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -54,6 +54,8 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; @@ -303,8 +305,10 @@ public class ViewKeyActivity extends ActionBarActivity implements Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { - setResult(RESULT_CANCELED); - finish(); + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + setResult(RESULT_CANCELED); + finish(); + } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java index 4927a4d24..d0c9cea5b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java @@ -18,7 +18,9 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Dialog; +import android.app.ProgressDialog; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; import android.os.Message; import android.os.Messenger; @@ -31,9 +33,10 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.util.Log; import java.util.HashMap; @@ -48,8 +51,6 @@ public class DeleteKeyDialogFragment extends DialogFragment { private TextView mMainMessage; private View mInflateView; - private Messenger mMessenger; - /** * Creates new instance of this delete file dialog fragment */ @@ -68,7 +69,7 @@ public class DeleteKeyDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final FragmentActivity activity = getActivity(); - mMessenger = getArguments().getParcelable(ARG_MESSENGER); + final Messenger messenger = getArguments().getParcelable(ARG_MESSENGER); final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); @@ -83,6 +84,8 @@ public class DeleteKeyDialogFragment extends DialogFragment { builder.setTitle(R.string.warning); + final boolean hasSecret; + // If only a single key has been selected if (masterKeyIds.length == 1) { long masterKeyId = masterKeyIds[0]; @@ -98,7 +101,7 @@ public class DeleteKeyDialogFragment extends DialogFragment { } ); String userId = (String) data.get(KeyRings.USER_ID); - boolean hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1; + hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1; // Set message depending on which key it is. mMainMessage.setText(getString( @@ -107,12 +110,12 @@ public class DeleteKeyDialogFragment extends DialogFragment { userId )); } catch (ProviderHelper.NotFoundException e) { - sendMessageToHandler(MESSAGE_ERROR, null); dismiss(); return null; } } else { mMainMessage.setText(R.string.key_deletion_confirmation_multi); + hasSecret = false; } builder.setIcon(R.drawable.ic_dialog_alert_holo_light); @@ -120,18 +123,45 @@ public class DeleteKeyDialogFragment extends DialogFragment { @Override public void onClick(DialogInterface dialog, int which) { - boolean success = false; - for (long masterKeyId : masterKeyIds) { - int count = activity.getContentResolver().delete( - KeyRingData.buildPublicKeyRingUri(masterKeyId), null, null - ); - success = count > 0; - } - if (success) { - sendMessageToHandler(MESSAGE_OKAY, null); - } else { - sendMessageToHandler(MESSAGE_ERROR, null); - } + // Send all information needed to service to import key in other thread + Intent intent = new Intent(getActivity(), KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_DELETE); + + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + getActivity(), + getString(R.string.progress_deleting), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + try { + Message msg = Message.obtain(); + msg.copyFrom(message); + messenger.send(msg); + } catch (RemoteException e) { + Log.e(Constants.TAG, "messenger error", e); + } + } + }; + + // fill values for this action + Bundle data = new Bundle(); + data.putLongArray(KeychainIntentService.DELETE_KEY_LIST, masterKeyIds); + data.putBoolean(KeychainIntentService.DELETE_IS_SECRET, hasSecret); + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(getActivity()); + + // start service with intent + getActivity().startService(intent); + dismiss(); } }); @@ -146,23 +176,4 @@ public class DeleteKeyDialogFragment extends DialogFragment { return builder.show(); } - /** - * Send message back to handler which is initialized in a activity - * - * @param what Message integer you want to send - */ - private void sendMessageToHandler(Integer what, Bundle data) { - Message msg = Message.obtain(); - msg.what = what; - if (data != null) { - msg.setData(data); - } - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } } -- cgit v1.2.3 From 9c9fc5330a402fb873708b998dac5f1ebf54b71c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 20 Aug 2014 23:09:20 +0200 Subject: small change to make android studio recognize a honeycomb-only block --- .../java/org/sufficientlysecure/keychain/ui/KeyListFragment.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 6a4039e98..96a332d3e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -292,8 +292,10 @@ public class KeyListFragment extends LoaderFragment mStickyList.setEmptyView(getActivity().findViewById(R.id.key_list_empty)); // end action mode, if any - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && mActionMode != null) { - mActionMode.finish(); + if (mActionMode != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mActionMode.finish(); + } } // The list should now be shown. -- cgit v1.2.3 From 0b07c5258fe4062dfe540ea3ef51471075379fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 23:13:37 +0200 Subject: Disable key import in sync adapter --- .../service/ContactSyncAdapterService.java | 77 +++++++++++----------- 1 file changed, 39 insertions(+), 38 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 43ed2dad0..e70e74d91 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -42,7 +42,7 @@ public class ContactSyncAdapterService extends Service { private class ContactSyncAdapter extends AbstractThreadedSyncAdapter { - private final AtomicBoolean importDone = new AtomicBoolean(false); +// private final AtomicBoolean importDone = new AtomicBoolean(false); public ContactSyncAdapter() { super(ContactSyncAdapterService.this, true); @@ -51,43 +51,44 @@ public class ContactSyncAdapterService extends Service { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, final SyncResult syncResult) { - importDone.set(false); - KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); - EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(), - new Handler.Callback() { - @Override - public boolean handleMessage(Message msg) { - Bundle data = msg.getData(); - switch (msg.arg1) { - case KeychainIntentServiceHandler.MESSAGE_OKAY: - Log.d(Constants.TAG, "Syncing... Done."); - synchronized (importDone) { - importDone.set(true); - importDone.notifyAll(); - } - return true; - case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS: - if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) && - data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) { - Log.d(Constants.TAG, "Syncing... Progress: " + - data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" + - data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)); - return false; - } - default: - Log.d(Constants.TAG, "Syncing... " + msg.toString()); - return false; - } - } - }))); - synchronized (importDone) { - try { - if (!importDone.get()) importDone.wait(); - } catch (InterruptedException e) { - Log.w(Constants.TAG, e); - return; - } - } + // TODO: Import is currently disabled for 2.8, until we implement proper origin management +// importDone.set(false); +// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); +// EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(), +// new Handler.Callback() { +// @Override +// public boolean handleMessage(Message msg) { +// Bundle data = msg.getData(); +// switch (msg.arg1) { +// case KeychainIntentServiceHandler.MESSAGE_OKAY: +// Log.d(Constants.TAG, "Syncing... Done."); +// synchronized (importDone) { +// importDone.set(true); +// importDone.notifyAll(); +// } +// return true; +// case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS: +// if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) && +// data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) { +// Log.d(Constants.TAG, "Syncing... Progress: " + +// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" + +// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)); +// return false; +// } +// default: +// Log.d(Constants.TAG, "Syncing... " + msg.toString()); +// return false; +// } +// } +// }))); +// synchronized (importDone) { +// try { +// if (!importDone.get()) importDone.wait(); +// } catch (InterruptedException e) { +// Log.w(Constants.TAG, e); +// return; +// } +// } ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this); } } -- cgit v1.2.3 From 418e922c78c365cd1c428f334de6814cbbc17b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 23:26:01 +0200 Subject: Enable sync adapter, changelog --- .../java/org/sufficientlysecure/keychain/KeychainApplication.java | 8 ++++++-- .../keychain/service/ContactSyncAdapterService.java | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index ead29e229..ca9af8a9d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -20,11 +20,13 @@ package org.sufficientlysecure.keychain; import android.accounts.Account; import android.accounts.AccountManager; import android.app.Application; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Environment; +import android.provider.ContactsContract; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.sufficientlysecure.keychain.helper.Preferences; @@ -112,8 +114,10 @@ public class KeychainApplication extends Application { AccountManager manager = AccountManager.get(context); Account[] accounts = manager.getAccountsByType(Constants.PACKAGE_NAME); if (accounts == null || accounts.length == 0) { - Account dummy = new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME); - manager.addAccountExplicitly(dummy, null, null); + Account account = new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME); + manager.addAccountExplicitly(account, null, null); + ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); + ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index e70e74d91..78d132df7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -51,6 +51,7 @@ public class ContactSyncAdapterService extends Service { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, final SyncResult syncResult) { + Log.d(Constants.TAG, "Performing a sync!"); // TODO: Import is currently disabled for 2.8, until we implement proper origin management // importDone.set(false); // KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); -- cgit v1.2.3 From 6e3af6605a1cd722c76fc4daa91ae2ae5207bbca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 23:55:01 +0200 Subject: Sync in KeychainIntentService on delete, import, save --- .../keychain/service/ContactSyncAdapterService.java | 13 +++++++++++++ .../keychain/service/KeychainIntentService.java | 8 ++++++++ 2 files changed, 21 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 78d132df7..506a30b46 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -21,6 +21,8 @@ import android.accounts.Account; import android.app.Service; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; +import android.content.ContentResolver; +import android.content.Context; import android.content.Intent; import android.content.SyncResult; import android.os.Bundle; @@ -29,9 +31,11 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; +import android.provider.ContactsContract; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.KeychainApplication; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ContactHelper; import org.sufficientlysecure.keychain.helper.EmailKeyHelper; import org.sufficientlysecure.keychain.util.Log; @@ -94,6 +98,15 @@ public class ContactSyncAdapterService extends Service { } } + public static void requestSync(Context context) { + Bundle extras = new Bundle(); + extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); + ContentResolver.requestSync( + new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME), + ContactsContract.AUTHORITY, + extras); + } + @Override public IBinder onBind(Intent intent) { return new ContactSyncAdapter().getSyncAdapterBinder(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index ad2932f92..764acd552 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -453,6 +453,9 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(this); + /* Output */ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); } catch (Exception e) { @@ -501,6 +504,8 @@ public class KeychainIntentService extends IntentService if (result.mSecret > 0) { providerHelper.consolidateDatabaseStep1(this); } + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(this); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } catch (Exception e) { @@ -708,6 +713,9 @@ public class KeychainIntentService extends IntentService } if (success) { + // make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(this); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); } -- cgit v1.2.3 From 3ace5052e7b7b63c2de745b5626d9d08773174b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 Aug 2014 23:56:17 +0200 Subject: Comment extra in requestSync --- .../sufficientlysecure/keychain/service/ContactSyncAdapterService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 506a30b46..909c3031c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -100,6 +100,7 @@ public class ContactSyncAdapterService extends Service { public static void requestSync(Context context) { Bundle extras = new Bundle(); + // no need to wait for internet connection! extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ContentResolver.requestSync( new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME), -- cgit v1.2.3 From 63ca81d8717bad8df9a9c159126612eb62867647 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 21 Aug 2014 00:02:27 +0200 Subject: Copyright (C) 2014 Vincent Breitmoser --- .../org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java | 1 + .../java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java | 1 + .../org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java | 1 + .../org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java | 1 + .../org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java | 1 + .../org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java | 1 + .../src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java | 1 + .../main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 2 +- .../main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 1 + .../java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java | 1 + .../java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java | 1 + .../main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java | 1 + .../keychain/pgp/exception/PgpGeneralMsgIdException.java | 2 +- .../org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java | 1 + .../java/org/sufficientlysecure/keychain/provider/KeychainContract.java | 1 + .../java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java | 1 + .../java/org/sufficientlysecure/keychain/provider/KeychainProvider.java | 1 + .../java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 1 + .../sufficientlysecure/keychain/provider/TemporaryStorageProvider.java | 1 + .../org/sufficientlysecure/keychain/service/KeychainIntentService.java | 1 + .../org/sufficientlysecure/keychain/service/OperationResultParcel.java | 1 + .../java/org/sufficientlysecure/keychain/service/OperationResults.java | 1 + .../java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java | 1 + .../java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java | 1 + .../main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java | 1 + .../main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java | 1 + .../java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java | 1 + .../java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java | 1 + .../main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java | 1 + .../java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java | 1 + .../java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java | 1 + 31 files changed, 31 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java index 8609a7082..55e6be9b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java index 1da66872d..8076a14f3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java index ce6498df1..7a63a7a42 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java index 7b5d5d4be..2c27c5c37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java index af058b618..34eb9fb0b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java index 80889f70d..bc7f001dc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java index 35020b815..3ef4b336e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index f3af51397..175045470 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 90abf05f5..caacb948e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index 341ca6d04..dda52d786 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java index 8dc28c2b3..4dfd93289 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index ebd110dc5..03dbe4860 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralMsgIdException.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralMsgIdException.java index 3700b4c34..aa0d86bb3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralMsgIdException.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralMsgIdException.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index e076fd9cc..21f0dddf6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index c239ea7f7..24d86dc4a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 041c4d904..36e94208d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index c5bf12143..b2a47cccd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann * Copyright (C) 2010-2014 Thialfihar + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 6447a180c..16ff2286b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java index 87c0cc0a6..a65d222da 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index ad2932f92..b7596ea4b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 3f48a2200..886f77068 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java index c59a7d172..f3d0b9e9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 490a8e738..6e06c4fa9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 728e6e1e1..8b99d474d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * Copyright (C) 2011 Senecaso * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 7663b7366..e2ad241e2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 96a332d3e..b4676f9b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2013-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java index b8386b144..248b8976a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 0e948bf7f..e524c3870 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 341e11d1d..48e9da87f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2013-2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java index 5a55b0dad..786537b25 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index 08243f06b..c37cb014e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser * * 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 -- cgit v1.2.3 From d1ef355f559c31d14e19bf6cf55efb91c8c65444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 00:29:49 +0200 Subject: Fix result handling in account settings --- .../remote/ui/AccountSettingsFragment.java | 23 ++++++++++------------ .../keychain/ui/CreateKeyFinalFragment.java | 6 +++--- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index 8468f5eca..2cab23e51 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -36,6 +36,8 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; +import org.sufficientlysecure.keychain.service.OperationResultParcel; +import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.ui.CreateKeyActivity; import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment; import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter; @@ -177,24 +179,19 @@ public class AccountSettingsFragment extends Fragment implements switch (requestCode) { case REQUEST_CODE_CREATE_KEY: { if (resultCode == Activity.RESULT_OK) { - // select newly created key - try { - long masterKeyId = new ProviderHelper(getActivity()) - .getCachedPublicKeyRing(data.getData()) - .extractOrGetMasterKeyId(); - mSelectKeyFragment.selectKey(masterKeyId); - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, "key not found!", e); + if (data != null && data.hasExtra(OperationResultParcel.EXTRA_RESULT)) { + OperationResults.SaveKeyringResult result = data.getParcelableExtra(OperationResultParcel.EXTRA_RESULT); + mSelectKeyFragment.selectKey(result.mRingMasterKeyId); + } else { + Log.e(Constants.TAG, "missing result!"); } } break; } - - default: - super.onActivityResult(requestCode, resultCode, data); - - break; } + + // execute activity's onActivityResult to show log notify + super.onActivityResult(requestCode, resultCode, data); } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 076f52a10..d804b9b70 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -187,7 +187,7 @@ public class CreateKeyFinalFragment extends Fragment { getActivity().startService(intent); } - private void uploadKey(final OperationResults.SaveKeyringResult editKeyResult) { + private void uploadKey(final OperationResults.SaveKeyringResult saveKeyResult) { // Send all information needed to service to upload key in other thread final Intent intent = new Intent(getActivity(), KeychainIntentService.class); @@ -195,7 +195,7 @@ public class CreateKeyFinalFragment extends Fragment { // set data uri as path to keyring Uri blobUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri( - editKeyResult.mRingMasterKeyId); + saveKeyResult.mRingMasterKeyId); intent.setData(blobUri); // fill values for this action @@ -221,7 +221,7 @@ public class CreateKeyFinalFragment extends Fragment { //Notify.Style.INFO); Intent data = new Intent(); - data.putExtra(OperationResultParcel.EXTRA_RESULT, editKeyResult); + data.putExtra(OperationResultParcel.EXTRA_RESULT, saveKeyResult); getActivity().setResult(Activity.RESULT_OK, data); getActivity().finish(); } -- cgit v1.2.3 From 4c6783215fc9007542feaaaeaa32e72800584c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 00:33:52 +0200 Subject: cleanup --- .../sufficientlysecure/keychain/pgp/PgpHelper.java | 71 ---------------------- 1 file changed, 71 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index 1cf027721..db360f810 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -29,7 +29,6 @@ import org.sufficientlysecure.keychain.util.Log; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.RandomAccessFile; import java.security.SecureRandom; import java.util.regex.Pattern; @@ -68,76 +67,6 @@ public class PgpHelper { } } -// public static final class content { -// public static final int unknown = 0; -// public static final int encrypted_data = 1; -// public static final int keys = 2; -// } -// -// public static int getStreamContent(Context context, InputStream inStream) throws IOException { -// -// InputStream in = PGPUtil.getDecoderStream(inStream); -// PGPObjectFactory pgpF = new PGPObjectFactory(in); -// Object object = pgpF.nextObject(); -// while (object != null) { -// if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) { -// return Id.content.keys; -// } else if (object instanceof PGPEncryptedDataList) { -// return Id.content.encrypted_data; -// } -// object = pgpF.nextObject(); -// } -// -// return Id.content.unknown; -// } - - /** - * Generate a random filename - * - * @param length - * @return - */ - public static String generateRandomFilename(int length) { - SecureRandom random = new SecureRandom(); - - byte bytes[] = new byte[length]; - random.nextBytes(bytes); - String result = ""; - for (int i = 0; i < length; ++i) { - int v = (bytes[i] + 256) % 64; - if (v < 10) { - result += (char) ('0' + v); - } else if (v < 36) { - result += (char) ('A' + v - 10); - } else if (v < 62) { - result += (char) ('a' + v - 36); - } else if (v == 62) { - result += '_'; - } else if (v == 63) { - result += '.'; - } - } - return result; - } - - /** - * Go once through stream to get length of stream. The length is later used to display progress - * when encrypting/decrypting - * - * @param in - * @return - * @throws IOException - */ - public static long getLengthOfStream(InputStream in) throws IOException { - long size = 0; - long n = 0; - byte dummy[] = new byte[0x10000]; - while ((n = in.read(dummy)) > 0) { - size += n; - } - return size; - } - /** * Deletes file securely by overwriting it with random data before deleting it. *

-- cgit v1.2.3 From 2930f83b2a49735a840f2adad4a4c3cb83ac07e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 11:19:44 +0200 Subject: Change account type --- .../src/main/java/org/sufficientlysecure/keychain/Constants.java | 3 +++ .../java/org/sufficientlysecure/keychain/KeychainApplication.java | 4 ++-- .../keychain/service/ContactSyncAdapterService.java | 4 ++-- .../sufficientlysecure/keychain/service/KeychainIntentService.java | 6 +++--- 4 files changed, 10 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 78b66464b..9f84da815 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -35,6 +35,9 @@ public final class Constants { public static final String PACKAGE_NAME = "org.sufficientlysecure.keychain"; + public static final String ACCOUNT_NAME = "OpenKeychain"; + public static final String ACCOUNT_TYPE = PACKAGE_NAME + ".account"; + // as defined in http://tools.ietf.org/html/rfc3156, section 7 public static final String NFC_MIME = "application/pgp-keys"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index ca9af8a9d..964342c60 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -112,9 +112,9 @@ public class KeychainApplication extends Application { public static void setupAccountAsNeeded(Context context) { AccountManager manager = AccountManager.get(context); - Account[] accounts = manager.getAccountsByType(Constants.PACKAGE_NAME); + Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE); if (accounts == null || accounts.length == 0) { - Account account = new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME); + Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); manager.addAccountExplicitly(account, null, null); ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 909c3031c..fbe914b78 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -98,12 +98,12 @@ public class ContactSyncAdapterService extends Service { } } - public static void requestSync(Context context) { + public static void requestSync() { Bundle extras = new Bundle(); // no need to wait for internet connection! extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ContentResolver.requestSync( - new Account(context.getString(R.string.app_name), Constants.PACKAGE_NAME), + new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), ContactsContract.AUTHORITY, extras); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 246804383..021e6bc07 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -455,7 +455,7 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); // make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(this); + ContactSyncAdapterService.requestSync(); /* Output */ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, saveResult); @@ -506,7 +506,7 @@ public class KeychainIntentService extends IntentService providerHelper.consolidateDatabaseStep1(this); } // make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(this); + ContactSyncAdapterService.requestSync(); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); } catch (Exception e) { @@ -715,7 +715,7 @@ public class KeychainIntentService extends IntentService if (success) { // make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(this); + ContactSyncAdapterService.requestSync(); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); } -- cgit v1.2.3 From 0c1e65bc8bbfed59d299e2f0ca7a6a30eef22664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 11:33:42 +0200 Subject: No need for setSyncAutomatically, this is only for network tickles --- .../java/org/sufficientlysecure/keychain/KeychainApplication.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 964342c60..aee6a5d70 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -115,9 +115,11 @@ public class KeychainApplication extends Application { Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE); if (accounts == null || accounts.length == 0) { Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); - manager.addAccountExplicitly(account, null, null); - ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); - ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); + if (manager.addAccountExplicitly(account, null, null)) { + ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); + } else { + Log.e(Constants.TAG, "Adding account failed!"); + } } } -- cgit v1.2.3 From 3c46c3c2dfd4ec6ec8b91eb43246c7d579f9b95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 11:36:47 +0200 Subject: Add account only on jelly bean and above --- .../keychain/KeychainApplication.java | 20 ++++++++++++-------- .../keychain/helper/ContactHelper.java | 3 +++ 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index aee6a5d70..37af95e28 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Environment; import android.provider.ContactsContract; @@ -111,14 +112,17 @@ public class KeychainApplication extends Application { } public static void setupAccountAsNeeded(Context context) { - AccountManager manager = AccountManager.get(context); - Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE); - if (accounts == null || accounts.length == 0) { - Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); - if (manager.addAccountExplicitly(account, null, null)) { - ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); - } else { - Log.e(Constants.TAG, "Adding account failed!"); + // only enabled for Jelly Bean because we need some newer methods in our sync adapter + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + AccountManager manager = AccountManager.get(context); + Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE); + if (accounts == null || accounts.length == 0) { + Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); + if (manager.addAccountExplicitly(account, null, null)) { + ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); + } else { + Log.e(Constants.TAG, "Adding account failed!"); + } } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 96e1b25af..b7c4dcb80 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.helper; import android.accounts.Account; import android.accounts.AccountManager; +import android.annotation.TargetApi; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentUris; @@ -252,6 +253,7 @@ public class ContactHelper { return new ArrayList(names); } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static Uri dataUriFromContactUri(Context context, Uri contactUri) { Cursor contactMasterKey = context.getContentResolver().query(contactUri, new String[]{ContactsContract.Data.DATA2}, null, null, null, null); @@ -367,6 +369,7 @@ public class ContactHelper { * * @return raw contact id or -1 if not found */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private static int findRawContactId(ContentResolver resolver, String fingerprint) { int rawContactId = -1; Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, ID_PROJECTION, -- cgit v1.2.3 From 562e379c56a96bc54df7b5ee4c5843771a14461a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 11:40:48 +0200 Subject: Fix nullpointer when revoking keys --- .../main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index f2d6d4c13..28692f638 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -339,7 +339,8 @@ public class EditKeyFragment extends LoaderFragment implements } else { mSaveKeyringParcel.mRevokeUserIds.add(userId); // not possible to revoke and change to primary user id - if (mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { + if (mSaveKeyringParcel.mChangePrimaryUserId != null + && mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { mSaveKeyringParcel.mChangePrimaryUserId = null; } } -- cgit v1.2.3 From b7de91ad5167ac55abc3c438c706e6a8d5dd4634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 14:07:37 +0200 Subject: Disable custom intent chooser --- .../keychain/ui/EncryptActivity.java | 107 +++++++++++---------- 1 file changed, 54 insertions(+), 53 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index d33e5116c..26df5cd26 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -309,59 +309,60 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn String title = isContentMessage() ? getString(R.string.title_share_message) : getString(R.string.title_share_file); - // fallback on Android 2.3, otherwise we would get weird results - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return Intent.createChooser(prototype, title); - } - - // prevent recursion aka Inception :P - String[] blacklist = new String[]{Constants.PACKAGE_NAME + ".ui.EncryptActivity"}; - - List targetedShareIntents = new ArrayList(); - - List resInfoList = getPackageManager().queryIntentActivities(prototype, 0); - List resInfoListFiltered = new ArrayList(); - if (!resInfoList.isEmpty()) { - for (ResolveInfo resolveInfo : resInfoList) { - // do not add blacklisted ones - if (resolveInfo.activityInfo == null || Arrays.asList(blacklist).contains(resolveInfo.activityInfo.name)) - continue; - - resInfoListFiltered.add(resolveInfo); - } - - if (!resInfoListFiltered.isEmpty()) { - // sorting for nice readability - Collections.sort(resInfoListFiltered, new Comparator() { - @Override - public int compare(ResolveInfo first, ResolveInfo second) { - String firstName = first.loadLabel(getPackageManager()).toString(); - String secondName = second.loadLabel(getPackageManager()).toString(); - return firstName.compareToIgnoreCase(secondName); - } - }); - - // create the custom intent list - for (ResolveInfo resolveInfo : resInfoListFiltered) { - Intent targetedShareIntent = (Intent) prototype.clone(); - targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName); - targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); - - LabeledIntent lIntent = new LabeledIntent(targetedShareIntent, - resolveInfo.activityInfo.packageName, - resolveInfo.loadLabel(getPackageManager()), - resolveInfo.activityInfo.icon); - targetedShareIntents.add(lIntent); - } - - // Create chooser with only one Intent in it - Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), title); - // append all other Intents - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{})); - return chooserIntent; - } - - } + // Disabled, produced an empty list on Sony (model will be inserted here) +// // fallback on Android 2.3, otherwise we would get weird results +// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { +// return Intent.createChooser(prototype, title); +// } +// +// // prevent recursion aka Inception :P +// String[] blacklist = new String[]{Constants.PACKAGE_NAME + ".ui.EncryptActivity"}; +// +// List targetedShareIntents = new ArrayList(); +// +// List resInfoList = getPackageManager().queryIntentActivities(prototype, 0); +// List resInfoListFiltered = new ArrayList(); +// if (!resInfoList.isEmpty()) { +// for (ResolveInfo resolveInfo : resInfoList) { +// // do not add blacklisted ones +// if (resolveInfo.activityInfo == null || Arrays.asList(blacklist).contains(resolveInfo.activityInfo.name)) +// continue; +// +// resInfoListFiltered.add(resolveInfo); +// } +// +// if (!resInfoListFiltered.isEmpty()) { +// // sorting for nice readability +// Collections.sort(resInfoListFiltered, new Comparator() { +// @Override +// public int compare(ResolveInfo first, ResolveInfo second) { +// String firstName = first.loadLabel(getPackageManager()).toString(); +// String secondName = second.loadLabel(getPackageManager()).toString(); +// return firstName.compareToIgnoreCase(secondName); +// } +// }); +// +// // create the custom intent list +// for (ResolveInfo resolveInfo : resInfoListFiltered) { +// Intent targetedShareIntent = (Intent) prototype.clone(); +// targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName); +// targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); +// +// LabeledIntent lIntent = new LabeledIntent(targetedShareIntent, +// resolveInfo.activityInfo.packageName, +// resolveInfo.loadLabel(getPackageManager()), +// resolveInfo.activityInfo.icon); +// targetedShareIntents.add(lIntent); +// } +// +// // Create chooser with only one Intent in it +// Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), title); +// // append all other Intents +// chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{})); +// return chooserIntent; +// } +// +// } // fallback to Android's default chooser return Intent.createChooser(prototype, title); -- cgit v1.2.3 From 7adff7c7df1d2e48c188b34c462673ac14ccc27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 14:41:32 +0200 Subject: Add info about device with intent chooser bug --- .../main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 26df5cd26..4cd694d48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -309,7 +309,7 @@ public class EncryptActivity extends DrawerActivity implements EncryptActivityIn String title = isContentMessage() ? getString(R.string.title_share_message) : getString(R.string.title_share_file); - // Disabled, produced an empty list on Sony (model will be inserted here) + // Disabled, produced an empty list on Huawei U8860 with Android Version 4.0.3 // // fallback on Android 2.3, otherwise we would get weird results // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // return Intent.createChooser(prototype, title); -- cgit v1.2.3 From aa35f6cffbd18fcd2c40d0bc602e9803ca015e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 15:20:49 +0200 Subject: Fixing build with Spongy Castle 1.51 --- .../keychain/pgp/PgpDecryptVerify.java | 8 +------ .../keychain/pgp/WrappedSignature.java | 27 ++++------------------ 2 files changed, 5 insertions(+), 30 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 7d113241b..828bee848 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -523,13 +523,7 @@ public class PgpDecryptVerify { // update signature buffer if signature is also present if (signature != null) { - try { - signature.update(buffer, 0, length); - } catch (SignatureException e) { - Log.e(Constants.TAG, "SignatureException -> Not a valid signature!", e); - signatureResultBuilder.validSignature(false); - signature = null; - } + signature.update(buffer, 0, length); } alreadyWritten += length; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index 03dbe4860..f24259ba7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -96,9 +96,6 @@ public class WrappedSignature { } catch (PGPException e) { // no matter Log.e(Constants.TAG, "exception reading embedded signatures", e); - } catch (IOException e) { - // no matter - Log.e(Constants.TAG, "exception reading embedded signatures", e); } return sigs; } @@ -150,27 +147,17 @@ public class WrappedSignature { } } - public void update(byte[] data, int offset, int length) throws PgpGeneralException { - try { - mSig.update(data, offset, length); - } catch(SignatureException e) { - throw new PgpGeneralException(e); - } + public void update(byte[] data, int offset, int length) { + mSig.update(data, offset, length); } - public void update(byte data) throws PgpGeneralException { - try { - mSig.update(data); - } catch(SignatureException e) { - throw new PgpGeneralException(e); - } + public void update(byte data) { + mSig.update(data); } public boolean verify() throws PgpGeneralException { try { return mSig.verify(); - } catch(SignatureException e) { - throw new PgpGeneralException(e); } catch(PGPException e) { throw new PgpGeneralException(e); } @@ -179,8 +166,6 @@ public class WrappedSignature { boolean verifySignature(PGPPublicKey key) throws PgpGeneralException { try { return mSig.verifyCertification(key); - } catch (SignatureException e) { - throw new PgpGeneralException("Sign!", e); } catch (PGPException e) { throw new PgpGeneralException("Error!", e); } @@ -189,8 +174,6 @@ public class WrappedSignature { boolean verifySignature(PGPPublicKey masterKey, PGPPublicKey subKey) throws PgpGeneralException { try { return mSig.verifyCertification(masterKey, subKey); - } catch (SignatureException e) { - throw new PgpGeneralException("Sign!", e); } catch (PGPException e) { throw new PgpGeneralException("Error!", e); } @@ -199,8 +182,6 @@ public class WrappedSignature { boolean verifySignature(PGPPublicKey key, String uid) throws PgpGeneralException { try { return mSig.verifyCertification(uid, key); - } catch (SignatureException e) { - throw new PgpGeneralException("Error!", e); } catch (PGPException e) { throw new PgpGeneralException("Error!", e); } -- cgit v1.2.3 From 3acbe9052f6923b3cc711bf64d8cd774cd26b6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 21 Aug 2014 15:40:09 +0200 Subject: Add ECDH and ECDSA values --- .../keychain/ui/dialog/AddSubkeyDialogFragment.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index 450e6a5f5..e07941267 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -149,6 +149,10 @@ public class AddSubkeyDialogFragment extends DialogFragment { } choices.add(new Choice(PublicKeyAlgorithmTags.RSA_GENERAL, getResources().getString( R.string.rsa))); + choices.add(new Choice(PublicKeyAlgorithmTags.ECDH, getResources().getString( + R.string.ecdh))); + choices.add(new Choice(PublicKeyAlgorithmTags.ECDSA, getResources().getString( + R.string.ecdsa))); ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, choices); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); -- cgit v1.2.3 From 152cd10b70400134588321688f8187c28a9fd7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 22 Aug 2014 08:53:16 +0200 Subject: Revert "No need for setSyncAutomatically, this is only for network tickles" This reverts commit 0c1e65bc8bbfed59d299e2f0ca7a6a30eef22664. Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java --- .../main/java/org/sufficientlysecure/keychain/KeychainApplication.java | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 37af95e28..57d74967b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -120,6 +120,7 @@ public class KeychainApplication extends Application { Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); if (manager.addAccountExplicitly(account, null, null)) { ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); + ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); } else { Log.e(Constants.TAG, "Adding account failed!"); } -- cgit v1.2.3 From 3d6f5e8ba1f86117a8a8d485fda30314e4a21db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 22 Aug 2014 09:01:37 +0200 Subject: Fix contact sync --- .../org/sufficientlysecure/keychain/helper/ContactHelper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index b7c4dcb80..016d6dc14 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -343,7 +343,7 @@ public class ContactHelper { // Delete fingerprints that are no longer present in OK for (String fingerprint : contactFingerprints) { resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, - new String[]{Constants.PACKAGE_NAME, fingerprint}); + new String[]{Constants.ACCOUNT_TYPE, fingerprint}); } } @@ -354,7 +354,7 @@ public class ContactHelper { private static Set getRawContactFingerprints(ContentResolver resolver) { HashSet result = new HashSet(); Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION, - ACCOUNT_TYPE_SELECTION, new String[]{Constants.PACKAGE_NAME}, null); + ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null); if (fingerprints != null) { while (fingerprints.moveToNext()) { result.add(fingerprints.getString(0)); @@ -373,7 +373,7 @@ public class ContactHelper { private static int findRawContactId(ContentResolver resolver, String fingerprint) { int rawContactId = -1; Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, ID_PROJECTION, - ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, new String[]{Constants.PACKAGE_NAME, fingerprint}, null, null); + ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, new String[]{Constants.ACCOUNT_TYPE, fingerprint}, null, null); if (raw != null) { if (raw.moveToNext()) { rawContactId = raw.getInt(0); @@ -388,8 +388,8 @@ public class ContactHelper { */ private static void insertContact(ArrayList ops, Context context, String fingerprint) { ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) - .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, context.getString(R.string.app_name)) - .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.PACKAGE_NAME) + .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME) + .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE) .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint) .build()); } -- cgit v1.2.3 From 71657d993c7efe5e700e488d2b3e5235196cd412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 23 Aug 2014 15:27:25 +0200 Subject: API: Fix re-seletion of keys on default account --- .../keychain/remote/OpenPgpService.java | 20 +++++++++++++------- .../keychain/remote/RemoteService.java | 5 +++-- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 6e9f2fad6..5340222d3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -23,6 +23,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import android.text.TextUtils; import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.OpenPgpMetadata; @@ -185,7 +186,7 @@ public class OpenPgpService extends RemoteService { } catch (PassphraseCacheService.KeyNotFoundException e) { // secret key that is set for this account is deleted? // show account config again! - return getCreateAccountIntent(data, data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME)); + return getCreateAccountIntent(data, getAccountName(data)); } } if (passphrase == null) { @@ -564,6 +565,16 @@ public class OpenPgpService extends RemoteService { return null; } + private String getAccountName(Intent data) { + String accName = data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME); + // if no account name is given use name "default" + if (TextUtils.isEmpty(accName)) { + accName = "default"; + } + Log.d(Constants.TAG, "accName: " + accName); + return accName; + } + // TODO: multi-threading private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() { @@ -574,12 +585,7 @@ public class OpenPgpService extends RemoteService { return errorResult; } - String accName; - if (data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME) != null) { - accName = data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME); - } else { - accName = "default"; - } + String accName = getAccountName(data); final AccountSettings accSettings = getAccSettings(accName); if (accSettings == null) { return getCreateAccountIntent(data, accName); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java index f70324e2c..e71b52ccd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; +import android.text.TextUtils; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.util.OpenPgpApi; @@ -160,7 +161,7 @@ public abstract class RemoteService extends Service { */ protected AccountSettings getAccSettings(String accountName) { String currentPkg = getCurrentCallingPackage(); - Log.d(Constants.TAG, "accountName: " + accountName); + Log.d(Constants.TAG, "getAccSettings accountName: "+ accountName); Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(currentPkg, accountName); @@ -171,7 +172,7 @@ public abstract class RemoteService extends Service { protected Intent getCreateAccountIntent(Intent data, String accountName) { String packageName = getCurrentCallingPackage(); - Log.d(Constants.TAG, "accountName: " + accountName); + Log.d(Constants.TAG, "getCreateAccountIntent accountName: " + accountName); Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_CREATE_ACCOUNT); -- cgit v1.2.3 From 783dae8804fee1f1594cc910d3570fcf6178015c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 24 Aug 2014 05:12:09 +0200 Subject: add ecc support --- .../keychain/keyimport/HkpKeyserver.java | 2 +- .../keychain/keyimport/ImportKeysListEntry.java | 23 ++- .../keychain/keyimport/KeybaseKeyserver.java | 2 +- .../keychain/pgp/PgpKeyHelper.java | 131 ++++++++++++-- .../keychain/pgp/PgpKeyOperation.java | 106 +++++++++--- .../keychain/pgp/UncachedKeyRing.java | 6 +- .../keychain/pgp/UncachedPublicKey.java | 23 ++- .../keychain/provider/KeychainContract.java | 1 + .../keychain/provider/KeychainDatabase.java | 24 ++- .../keychain/provider/KeychainProvider.java | 2 + .../keychain/provider/ProviderHelper.java | 2 +- .../keychain/service/OperationResultParcel.java | 7 +- .../keychain/service/SaveKeyringParcel.java | 29 +++- .../keychain/ui/CreateKeyFinalFragment.java | 10 +- .../keychain/ui/ViewCertActivity.java | 2 +- .../keychain/ui/adapter/ImportKeysAdapter.java | 4 +- .../keychain/ui/adapter/SubkeysAdapter.java | 21 ++- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 7 +- .../ui/dialog/AddSubkeyDialogFragment.java | 188 ++++++++++++++------- .../sufficientlysecure/keychain/util/Choice.java | 13 +- 20 files changed, 454 insertions(+), 149 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 69ac2551f..e30401180 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -283,7 +283,7 @@ public class HkpKeyserver extends Keyserver { entry.setBitStrength(Integer.parseInt(matcher.group(3))); final int algorithmId = Integer.decode(matcher.group(2)); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId)); + entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, null, null)); // group 1 contains the full fingerprint (v4) or the long key id if available // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index 30e93f957..da70f1505 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -39,7 +39,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable { private boolean mExpired; private Date mDate; // TODO: not displayed private String mFingerprintHex; - private int mBitStrength; + private Integer mBitStrength; + private String mCurveOid; private String mAlgorithm; private boolean mSecretKey; private String mPrimaryUserId; @@ -162,10 +163,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable { this.mFingerprintHex = fingerprintHex; } - public int getBitStrength() { + public Integer getBitStrength() { return mBitStrength; } + public String getCurveOid() { + return mCurveOid; + } + public void setBitStrength(int bitStrength) { this.mBitStrength = bitStrength; } @@ -258,13 +263,15 @@ public class ImportKeysListEntry implements Serializable, Parcelable { mPrimaryUserId = mUserIds.get(0); } - this.mKeyId = key.getKeyId(); - this.mKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mKeyId); + mKeyId = key.getKeyId(); + mKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mKeyId); - this.mRevoked = key.isRevoked(); - this.mFingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); - this.mBitStrength = key.getBitStrength(); + mRevoked = key.isRevoked(); + mFingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); + mBitStrength = key.getBitStrength(); + mCurveOid = key.getCurveOid(); final int algorithm = key.getAlgorithm(); - this.mAlgorithm = PgpKeyHelper.getAlgorithmInfo(context, algorithm); + mAlgorithm = PgpKeyHelper.getAlgorithmInfo(context, algorithm, mBitStrength, mCurveOid); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java index 0ca6f07fd..cbd06da90 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java @@ -75,7 +75,7 @@ public class KeybaseKeyserver extends Keyserver { entry.setExtraData(username); final int algorithmId = match.getAlgorithmId(); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId)); + entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, null, null)); final int bitStrength = match.getBitStrength(); entry.setBitStrength(bitStrength); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index 0c640538f..22956c8af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -24,10 +24,16 @@ import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.bcpg.ECPublicBCPGKey; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.util.Log; import java.security.DigestException; @@ -37,18 +43,14 @@ import java.util.Locale; public class PgpKeyHelper { - public static String getAlgorithmInfo(int algorithm) { - return getAlgorithmInfo(null, algorithm, 0); - } - - public static String getAlgorithmInfo(Context context, int algorithm) { - return getAlgorithmInfo(context, algorithm, 0); + public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) { + return getAlgorithmInfo(null, algorithm, keySize, oid); } /** * Based on OpenPGP Message Format */ - public static String getAlgorithmInfo(Context context, int algorithm, int keySize) { + public static String getAlgorithmInfo(Context context, int algorithm, Integer keySize, String oid) { String algorithmStr; switch (algorithm) { @@ -69,10 +71,19 @@ public class PgpKeyHelper { break; } - case PublicKeyAlgorithmTags.ECDSA: + case PublicKeyAlgorithmTags.ECDSA: { + if (oid == null) { + return "ECDSA"; + } + String oidName = PgpKeyHelper.getCurveInfo(context, oid); + return "ECDSA (" + oidName + ")"; + } case PublicKeyAlgorithmTags.ECDH: { - algorithmStr = "ECC"; - break; + if (oid == null) { + return "ECDH"; + } + String oidName = PgpKeyHelper.getCurveInfo(context, oid); + return "ECDH (" + oidName + ")"; } default: { @@ -90,6 +101,106 @@ public class PgpKeyHelper { return algorithmStr; } + public static String getAlgorithmInfo(Algorithm algorithm, Integer keySize, Curve curve) { + return getAlgorithmInfo(null, algorithm, keySize, curve); + } + + /** + * Based on OpenPGP Message Format + */ + public static String getAlgorithmInfo(Context context, Algorithm algorithm, Integer keySize, Curve curve) { + String algorithmStr; + + switch (algorithm) { + case RSA: { + algorithmStr = "RSA"; + break; + } + case DSA: { + algorithmStr = "DSA"; + break; + } + + case ELGAMAL: { + algorithmStr = "ElGamal"; + break; + } + + case ECDSA: { + algorithmStr = "ECDSA"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + case ECDH: { + algorithmStr = "ECDH"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + + default: { + if (context != null) { + algorithmStr = context.getResources().getString(R.string.unknown_algorithm); + } else { + algorithmStr = "unknown"; + } + break; + } + } + if (keySize != null && keySize > 0) + return algorithmStr + ", " + keySize + " bit"; + else + return algorithmStr; + } + + // Return name of a curve. These are names, no need for translation + public static String getCurveInfo(Context context, Curve curve) { + switch(curve) { + case NIST_P256: + return "NIST P-256"; + case NIST_P384: + return "NIST P-384"; + case NIST_P521: + return "NIST P-521"; + + /* see SaveKeyringParcel + case BRAINPOOL_P256: + return "Brainpool P-256"; + case BRAINPOOL_P384: + return "Brainpool P-384"; + case BRAINPOOL_P512: + return "Brainpool P-512"; + */ + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + + public static String getCurveInfo(Context context, String oidStr) { + ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidStr); + + String name; + name = NISTNamedCurves.getName(oid); + if (name != null) { + return name; + } + name = TeleTrusTNamedCurves.getName(oid); + if (name != null) { + return name; + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + /** * Converts fingerprint to hex (optional: with whitespaces after 4 characters) *

diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 175045470..967a7caa9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -20,12 +20,12 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPKeyFlags; import org.spongycastle.openpgp.PGPKeyPair; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; @@ -52,6 +52,8 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -66,6 +68,7 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; import java.util.Arrays; import java.util.Date; import java.util.Iterator; @@ -155,31 +158,65 @@ public class PgpKeyOperation { mProgress.peek().setProgress(message, current, 100); } + private ECGenParameterSpec getEccParameterSpec(Curve curve) { + switch (curve) { + case NIST_P256: return new ECGenParameterSpec("P-256"); + case NIST_P384: return new ECGenParameterSpec("P-384"); + case NIST_P521: return new ECGenParameterSpec("P-521"); + + // @see SaveKeyringParcel + // case BRAINPOOL_P256: return new ECGenParameterSpec("brainpoolp256r1"); + // case BRAINPOOL_P384: return new ECGenParameterSpec("brainpoolp384r1"); + // case BRAINPOOL_P512: return new ECGenParameterSpec("brainpoolp512r1"); + } + throw new RuntimeException("Invalid choice! (can't happen)"); + } + /** Creates new secret key. */ - private PGPKeyPair createKey(int algorithmChoice, int keySize, OperationLog log, int indent) { + private PGPKeyPair createKey(SubkeyAdd add, OperationLog log, int indent) { try { - if (keySize < 512) { - log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_KEYSIZE_512, indent); - return null; + // Some safety checks + if (add.mAlgorithm == Algorithm.ECDH || add.mAlgorithm == Algorithm.ECDSA) { + if (add.mCurve == null) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_CURVE, indent); + return null; + } + } else { + if (add.mKeySize == null) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_KEYSIZE, indent); + return null; + } + if (add.mKeySize < 512) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_KEYSIZE_512, indent); + return null; + } } int algorithm; KeyPairGenerator keyGen; - switch (algorithmChoice) { - case PublicKeyAlgorithmTags.DSA: { + switch (add.mAlgorithm) { + case DSA: { + if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_DSA, indent); + return null; + } progress(R.string.progress_generating_dsa, 30); keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - keyGen.initialize(keySize, new SecureRandom()); + keyGen.initialize(add.mKeySize, new SecureRandom()); algorithm = PGPPublicKey.DSA; break; } - case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: { + case ELGAMAL: { + if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ELGAMAL, indent); + return null; + } progress(R.string.progress_generating_elgamal, 30); keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - BigInteger p = Primes.getBestPrime(keySize); + BigInteger p = Primes.getBestPrime(add.mKeySize); BigInteger g = new BigInteger("2"); ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g); @@ -189,15 +226,44 @@ public class PgpKeyOperation { break; } - case PublicKeyAlgorithmTags.RSA_GENERAL: { + case RSA: { progress(R.string.progress_generating_rsa, 30); keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - keyGen.initialize(keySize, new SecureRandom()); + keyGen.initialize(add.mKeySize, new SecureRandom()); algorithm = PGPPublicKey.RSA_GENERAL; break; } + case ECDSA: { + if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ECDSA, indent); + return null; + } + progress(R.string.progress_generating_ecdsa, 30); + ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve); + keyGen = KeyPairGenerator.getInstance("ECDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); + keyGen.initialize(ecParamSpec, new SecureRandom()); + + algorithm = PGPPublicKey.ECDSA; + break; + } + + case ECDH: { + // make sure there are no sign or certify flags set + if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ECDH, indent); + return null; + } + progress(R.string.progress_generating_ecdh, 30); + ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve); + keyGen = KeyPairGenerator.getInstance("ECDH", Constants.BOUNCY_CASTLE_PROVIDER_NAME); + keyGen.initialize(ecParamSpec, new SecureRandom()); + + algorithm = PGPPublicKey.ECDH; + break; + } + default: { log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent); return null; @@ -210,7 +276,8 @@ public class PgpKeyOperation { } catch(NoSuchProviderException e) { throw new RuntimeException(e); } catch(NoSuchAlgorithmException e) { - throw new RuntimeException(e); + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent); + return null; } catch(InvalidAlgorithmParameterException e) { throw new RuntimeException(e); } catch(PGPException e) { @@ -252,13 +319,8 @@ public class PgpKeyOperation { return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - if (add.mAlgorithm == PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT) { - log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_MASTER_ELGAMAL, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - subProgressPush(10, 30); - PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize, log, indent); + PGPKeyPair keyPair = createKey(add, log, indent); subProgressPop(); // return null if this failed (an error will already have been logged by createKey) @@ -690,8 +752,8 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, Integer.toString(add.mKeysize), - PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm) ); + log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, + PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) ); if (add.mExpiry == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1); @@ -708,7 +770,7 @@ public class PgpKeyOperation { (i-1) * (100 / saveParcel.mAddSubKeys.size()), i * (100 / saveParcel.mAddSubKeys.size()) ); - PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize, log, indent); + PGPKeyPair keyPair = createKey(add, log, indent); subProgressPop(); if (keyPair == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent +1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index caacb948e..9effe4e67 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -37,7 +37,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; -import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -58,7 +57,8 @@ import java.util.TreeSet; * This class and its relatives UncachedPublicKey and UncachedSecretKey are * used to move around pgp key rings in non crypto related (UI, mostly) code. * It should be used for simple inspection only until it saved in the database, - * all actual crypto operations should work with WrappedKeyRings exclusively. + * all actual crypto operations should work with CanonicalizedKeyRings + * exclusively. * * This class is also special in that it can hold either the PGPPublicKeyRing * or PGPSecretKeyRing derivate of the PGPKeyRing class, since these are @@ -591,7 +591,7 @@ public class UncachedKeyRing { } - // if we already have a cert, and this one is not newer: skip it + // if we already have a cert, and this one is older: skip it if (selfCert != null && cert.getCreationTime().before(selfCert.getCreationTime())) { log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB_DUP, indent); redundantCerts += 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index dda52d786..c7a8bb1d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -18,6 +18,10 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.bcpg.ECPublicBCPGKey; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; @@ -94,10 +98,23 @@ public class UncachedPublicKey { return mPublicKey.getAlgorithm(); } - public int getBitStrength() { + public Integer getBitStrength() { + if (isEC()) { + return null; + } return mPublicKey.getBitStrength(); } + public String getCurveOid() { + if ( ! isEC()) { + return null; + } + if ( ! (mPublicKey.getPublicKeyPacket().getKey() instanceof ECPublicBCPGKey)) { + return null; + } + return ((ECPublicBCPGKey) mPublicKey.getPublicKeyPacket().getKey()).getCurveOID().getId(); + } + /** Returns the primary user id, as indicated by the public key's self certificates. * * This is an expensive operation, since potentially a lot of certificates (and revocations) @@ -186,6 +203,10 @@ public class UncachedPublicKey { return getAlgorithm() == PGPPublicKey.DSA; } + public boolean isEC() { + return getAlgorithm() == PGPPublicKey.ECDH || getAlgorithm() == PGPPublicKey.ECDSA; + } + @SuppressWarnings("unchecked") // TODO make this safe public int getKeyUsage() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 24d86dc4a..4f6e878b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -39,6 +39,7 @@ public class KeychainContract { String FINGERPRINT = "fingerprint"; String KEY_SIZE = "key_size"; + String KEY_CURVE_OID = "key_curve_oid"; String CAN_SIGN = "can_sign"; String CAN_ENCRYPT = "can_encrypt"; String CAN_CERTIFY = "can_certify"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 36e94208d..0bb43d47f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -52,7 +52,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 2; + private static final int DATABASE_VERSION = 3; static Boolean apgHack = false; public interface Tables { @@ -86,6 +86,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + KeysColumns.KEY_ID + " INTEGER, " + KeysColumns.KEY_SIZE + " INTEGER, " + + KeysColumns.KEY_CURVE_OID + " TEXT, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.FINGERPRINT + " BLOB, " @@ -202,13 +203,20 @@ public class KeychainDatabase extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion == 1) { - // add has_secret for all who are upgrading from a beta version - try { - db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN"); - } catch (Exception e) { - // never mind, the column probably already existed - } + // add has_secret for all who are upgrading from a beta version + switch (oldVersion) { + case 1: + try { + db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN"); + } catch(Exception e){ + // never mind, the column probably already existed + } + case 2: + try { + db.execSQL("ALTER TABLE keys ADD COLUMN " + KeysColumns.KEY_CURVE_OID + " TEXT"); + } catch(Exception e){ + // never mind, the column probably already existed + } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index b2a47cccd..f6df4a3eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -246,6 +246,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); projectionMap.put(KeyRings.KEY_SIZE, Tables.KEYS + "." + Keys.KEY_SIZE); + projectionMap.put(KeyRings.KEY_CURVE_OID, Tables.KEYS + "." + Keys.KEY_CURVE_OID); projectionMap.put(KeyRings.IS_REVOKED, Tables.KEYS + "." + Keys.IS_REVOKED); projectionMap.put(KeyRings.CAN_CERTIFY, Tables.KEYS + "." + Keys.CAN_CERTIFY); projectionMap.put(KeyRings.CAN_ENCRYPT, Tables.KEYS + "." + Keys.CAN_ENCRYPT); @@ -412,6 +413,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK); projectionMap.put(Keys.KEY_ID, Keys.KEY_ID); projectionMap.put(Keys.KEY_SIZE, Keys.KEY_SIZE); + projectionMap.put(Keys.KEY_CURVE_OID, Keys.KEY_CURVE_OID); projectionMap.put(Keys.IS_REVOKED, Keys.IS_REVOKED); projectionMap.put(Keys.CAN_CERTIFY, Keys.CAN_CERTIFY); projectionMap.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 16ff2286b..bb095c340 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -62,7 +62,6 @@ import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressFixedScaler; -import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -328,6 +327,7 @@ public class ProviderHelper { values.put(Keys.KEY_ID, key.getKeyId()); values.put(Keys.KEY_SIZE, key.getBitStrength()); + values.put(Keys.KEY_CURVE_OID, key.getCurveOid()); values.put(Keys.ALGORITHM, key.getAlgorithm()); values.put(Keys.FINGERPRINT, key.getFingerprint()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 886f77068..b69ecef34 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -347,9 +347,14 @@ public class OperationResultParcel implements Parcelable { MSG_CR_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), MSG_CR_ERROR_NULL_EXPIRY(R.string.msg_cr_error_null_expiry), MSG_CR_ERROR_KEYSIZE_512 (R.string.msg_cr_error_keysize_512), + MSG_CR_ERROR_NO_KEYSIZE (R.string.msg_cr_error_no_keysize), + MSG_CR_ERROR_NO_CURVE (R.string.msg_cr_error_no_curve), MSG_CR_ERROR_UNKNOWN_ALGO (R.string.msg_cr_error_unknown_algo), MSG_CR_ERROR_INTERNAL_PGP (R.string.msg_cr_error_internal_pgp), - MSG_CR_ERROR_MASTER_ELGAMAL (R.string.msg_cr_error_master_elgamal), + MSG_CR_ERROR_FLAGS_DSA (R.string.msg_cr_error_flags_dsa), + MSG_CR_ERROR_FLAGS_ELGAMAL (R.string.msg_cr_error_flags_elgamal), + MSG_CR_ERROR_FLAGS_ECDSA (R.string.msg_cr_error_flags_ecdsa), + MSG_CR_ERROR_FLAGS_ECDH (R.string.msg_cr_error_flags_ecdh), // secret key modify MSG_MF (R.string.msg_mr), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 6e06c4fa9..996ce6a5a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -80,14 +80,16 @@ public class SaveKeyringParcel implements Parcelable { // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { - public int mAlgorithm; - public int mKeysize; + public Algorithm mAlgorithm; + public Integer mKeySize; + public Curve mCurve; public int mFlags; public Long mExpiry; - public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { + public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) { mAlgorithm = algorithm; - mKeysize = keysize; + mKeySize = keySize; + mCurve = curve; mFlags = flags; mExpiry = expiry; } @@ -95,7 +97,8 @@ public class SaveKeyringParcel implements Parcelable { @Override public String toString() { String out = "mAlgorithm: " + mAlgorithm + ", "; - out += "mKeysize: " + mKeysize + ", "; + out += "mKeySize: " + mKeySize + ", "; + out += "mCurve: " + mCurve + ", "; out += "mFlags: " + mFlags; out += "mExpiry: " + mExpiry; @@ -214,4 +217,20 @@ public class SaveKeyringParcel implements Parcelable { return out; } + + // All supported algorithms + public enum Algorithm { + RSA, DSA, ELGAMAL, ECDSA, ECDH + } + + // All curves defined in the standard + // http://www.bouncycastle.org/wiki/pages/viewpage.action?pageId=362269 + public enum Curve { + NIST_P256, NIST_P384, NIST_P521, + + // these are supported by gpg, but they are not in rfc6637 and not supported by BouncyCastle yet + // (adding support would be trivial though -> JcaPGPKeyConverter.java:190) + // BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512 + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index d804b9b70..69f4af04b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -165,9 +166,12 @@ public class CreateKeyFinalFragment extends Fragment { Bundle data = new Bundle(); SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.CERTIFY_OTHER, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.SIGN_DATA, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); String userId = KeyRing.createUserId(mName, mEmail, null); parcel.mAddUserIds.add(userId); parcel.mChangePrimaryUserId = userId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 48e9da87f..92f38a44c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -167,7 +167,7 @@ public class ViewCertActivity extends ActionBarActivity mStatus.setTextColor(getResources().getColor(R.color.black)); } - String algorithmStr = PgpKeyHelper.getAlgorithmInfo(this, sig.getKeyAlgorithm(), 0); + String algorithmStr = PgpKeyHelper.getAlgorithmInfo(this, sig.getKeyAlgorithm(), null, null); mAlgorithm.setText(algorithmStr); mRowReason.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 1f809cc51..1fed58721 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -155,8 +155,8 @@ public class ImportKeysAdapter extends ArrayAdapter { // don't show full fingerprint on key import holder.fingerprint.setVisibility(View.GONE); - if (entry.getBitStrength() != 0 && entry.getAlgorithm() != null) { - holder.algorithm.setText("" + entry.getBitStrength() + "/" + entry.getAlgorithm()); + if (entry.getAlgorithm() != null) { + holder.algorithm.setText(entry.getAlgorithm()); holder.algorithm.setVisibility(View.VISIBLE); } else { holder.algorithm.setVisibility(View.INVISIBLE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 9958b33a1..489cbcefb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -52,6 +52,7 @@ public class SubkeysAdapter extends CursorAdapter { Keys.RANK, Keys.ALGORITHM, Keys.KEY_SIZE, + Keys.KEY_CURVE_OID, Keys.HAS_SECRET, Keys.CAN_CERTIFY, Keys.CAN_ENCRYPT, @@ -66,14 +67,15 @@ public class SubkeysAdapter extends CursorAdapter { private static final int INDEX_RANK = 2; private static final int INDEX_ALGORITHM = 3; private static final int INDEX_KEY_SIZE = 4; - private static final int INDEX_HAS_SECRET = 5; - private static final int INDEX_CAN_CERTIFY = 6; - private static final int INDEX_CAN_ENCRYPT = 7; - private static final int INDEX_CAN_SIGN = 8; - private static final int INDEX_IS_REVOKED = 9; - private static final int INDEX_CREATION = 10; - private static final int INDEX_EXPIRY = 11; - private static final int INDEX_FINGERPRINT = 12; + private static final int INDEX_KEY_CURVE_OID = 5; + private static final int INDEX_HAS_SECRET = 6; + private static final int INDEX_CAN_CERTIFY = 7; + private static final int INDEX_CAN_ENCRYPT = 8; + private static final int INDEX_CAN_SIGN = 9; + private static final int INDEX_IS_REVOKED = 10; + private static final int INDEX_CREATION = 11; + private static final int INDEX_EXPIRY = 12; + private static final int INDEX_FINGERPRINT = 13; public SubkeysAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) { @@ -141,7 +143,8 @@ public class SubkeysAdapter extends CursorAdapter { String algorithmStr = PgpKeyHelper.getAlgorithmInfo( context, cursor.getInt(INDEX_ALGORITHM), - cursor.getInt(INDEX_KEY_SIZE) + cursor.getInt(INDEX_KEY_SIZE), + cursor.getString(INDEX_KEY_CURVE_OID) ); vKeyId.setText(keyIdStr); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java index a1dfeb10c..d50318fb4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -42,14 +42,10 @@ public class SubkeysAddedAdapter extends ArrayAdapter mData; - public SubkeysAddedAdapter(Activity activity, List data) { super(activity, -1, data); mActivity = activity; mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mData = data; } static class ViewHolder { @@ -103,7 +99,8 @@ public class SubkeysAddedAdapter extends ArrayAdapter choices = new ArrayList(); - choices.add(new Choice(PublicKeyAlgorithmTags.DSA, getResources().getString( - R.string.dsa))); - if (!mWillBeMasterKey) { - choices.add(new Choice(PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, getResources().getString( - R.string.elgamal))); - } - choices.add(new Choice(PublicKeyAlgorithmTags.RSA_GENERAL, getResources().getString( - R.string.rsa))); - choices.add(new Choice(PublicKeyAlgorithmTags.ECDH, getResources().getString( - R.string.ecdh))); - choices.add(new Choice(PublicKeyAlgorithmTags.ECDSA, getResources().getString( - R.string.ecdsa))); - ArrayAdapter adapter = new ArrayAdapter(context, - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mAlgorithmSpinner.setAdapter(adapter); - // make RSA the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == PublicKeyAlgorithmTags.RSA_GENERAL) { - mAlgorithmSpinner.setSelection(i); - break; + { + ArrayList> choices = new ArrayList>(); + choices.add(new Choice(Algorithm.DSA, getResources().getString( + R.string.dsa))); + if (!mWillBeMasterKey) { + choices.add(new Choice(Algorithm.ELGAMAL, getResources().getString( + R.string.elgamal))); + } + choices.add(new Choice(Algorithm.RSA, getResources().getString( + R.string.rsa))); + choices.add(new Choice(Algorithm.ECDSA, getResources().getString( + R.string.ecdsa))); + choices.add(new Choice(Algorithm.ECDH, getResources().getString( + R.string.ecdh))); + ArrayAdapter> adapter = new ArrayAdapter>(context, + android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mAlgorithmSpinner.setAdapter(adapter); + // make RSA the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Algorithm.RSA) { + mAlgorithmSpinner.setSelection(i); + break; + } } } @@ -172,6 +178,36 @@ public class AddSubkeyDialogFragment extends DialogFragment { mKeySizeSpinner.setAdapter(keySizeAdapter); mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length + { + ArrayList> choices = new ArrayList>(); + + choices.add(new Choice(Curve.NIST_P256, getResources().getString( + R.string.key_curve_nist_p256))); + choices.add(new Choice(Curve.NIST_P384, getResources().getString( + R.string.key_curve_nist_p384))); + choices.add(new Choice(Curve.NIST_P521, getResources().getString( + R.string.key_curve_nist_p521))); + + /* @see SaveKeyringParcel + choices.add(new Choice(Curve.BRAINPOOL_P256, getResources().getString( + R.string.key_curve_bp_p256))); + choices.add(new Choice(Curve.BRAINPOOL_P384, getResources().getString( + R.string.key_curve_bp_p384))); + choices.add(new Choice(Curve.BRAINPOOL_P512, getResources().getString( + R.string.key_curve_bp_p512))); + */ + + ArrayAdapter> adapter = new ArrayAdapter>(context, + android.R.layout.simple_spinner_item, choices); + mCurveSpinner.setAdapter(adapter); + // make NIST P-256 the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Curve.NIST_P256) { + mCurveSpinner.setSelection(i); + break; + } + } + } dialog.setCancelable(true); @@ -211,7 +247,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - updateUiForAlgorithm(((Choice) parent.getSelectedItem()).getId()); + updateUiForAlgorithm(((Choice) parent.getSelectedItem()).getId()); setCustomKeyVisibility(); setOkButtonAvailability(alertDialog); @@ -241,11 +277,16 @@ public class AddSubkeyDialogFragment extends DialogFragment { return; } - // dismiss only if at least one flag is selected - dismiss(); - - Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem(); - int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength()); + Algorithm algorithm = ((Choice) mAlgorithmSpinner.getSelectedItem()).getId(); + Curve curve = null; + Integer keySize = null; + // For EC keys, add a curve + if (algorithm == Algorithm.ECDH || algorithm == Algorithm.ECDSA) { + curve = ((Choice) mCurveSpinner.getSelectedItem()).getId(); + // Otherwise, get a keysize + } else { + keySize = getProperKeyLength(algorithm, getSelectedKeyLength()); + } int flags = 0; if (mFlagCertify.isChecked()) { @@ -276,12 +317,12 @@ public class AddSubkeyDialogFragment extends DialogFragment { } SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd( - newKeyAlgorithmChoice.getId(), - newKeySize, - flags, - expiry + algorithm, keySize, curve, flags, expiry ); mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey); + + // finally, dismiss the dialogue + dismiss(); } }); negativeButton.setOnClickListener(new View.OnClickListener() { @@ -323,16 +364,16 @@ public class AddSubkeyDialogFragment extends DialogFragment { * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is * inappropriate. */ - private int getProperKeyLength(int algorithmId, int currentKeyLength) { + private int getProperKeyLength(Algorithm algorithm, int currentKeyLength) { final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; int properKeyLength = -1; - switch (algorithmId) { - case PublicKeyAlgorithmTags.RSA_GENERAL: + switch (algorithm) { + case RSA: if (currentKeyLength > 1024 && currentKeyLength <= 16384) { properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); } break; - case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: + case ELGAMAL: int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; for (int i = 0; i < elGamalSupportedLengths.length; i++) { elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); @@ -347,7 +388,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { } properKeyLength = elGamalSupportedLengths[minimalIndex]; break; - case PublicKeyAlgorithmTags.DSA: + case DSA: if (currentKeyLength >= 512 && currentKeyLength <= 1024) { properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); } @@ -357,10 +398,10 @@ public class AddSubkeyDialogFragment extends DialogFragment { } private void setOkButtonAvailability(AlertDialog alertDialog) { - final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem(); - final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem()); - final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize); - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0); + Algorithm algorithm = ((Choice) mAlgorithmSpinner.getSelectedItem()).getId(); + boolean enabled = algorithm == Algorithm.ECDSA || algorithm == Algorithm.ECDH + || getProperKeyLength(algorithm, getSelectedKeyLength()) > 0; + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled); } private void setCustomKeyVisibility() { @@ -376,18 +417,20 @@ public class AddSubkeyDialogFragment extends DialogFragment { // hide keyboard after setting visibility to gone if (visibility == View.GONE) { InputMethodManager imm = (InputMethodManager) - getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE); + getActivity().getSystemService(FragmentActivity.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mCustomKeyEditText.getWindowToken(), 0); } } - private void updateUiForAlgorithm(int algorithmId) { + private void updateUiForAlgorithm(Algorithm algorithm) { final ArrayAdapter keySizeAdapter = (ArrayAdapter) mKeySizeSpinner.getAdapter(); - final Object selectedItem = mKeySizeSpinner.getSelectedItem(); keySizeAdapter.clear(); - switch (algorithmId) { - case PublicKeyAlgorithmTags.RSA_GENERAL: + switch (algorithm) { + case RSA: replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); + mKeySizeSpinner.setSelection(1); + mKeySizeRow.setVisibility(View.VISIBLE); + mCurveRow.setVisibility(View.GONE); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); // allowed flags: mFlagSign.setEnabled(true); @@ -409,8 +452,11 @@ public class AddSubkeyDialogFragment extends DialogFragment { } mFlagAuthenticate.setChecked(false); break; - case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: + case ELGAMAL: replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); + mKeySizeSpinner.setSelection(3); + mKeySizeRow.setVisibility(View.VISIBLE); + mCurveRow.setVisibility(View.GONE); mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length // allowed flags: mFlagCertify.setChecked(false); @@ -422,8 +468,11 @@ public class AddSubkeyDialogFragment extends DialogFragment { mFlagAuthenticate.setChecked(false); mFlagAuthenticate.setEnabled(false); break; - case PublicKeyAlgorithmTags.DSA: + case DSA: replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); + mKeySizeSpinner.setSelection(2); + mKeySizeRow.setVisibility(View.VISIBLE); + mCurveRow.setVisibility(View.GONE); mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); // allowed flags: mFlagCertify.setChecked(false); @@ -435,16 +484,37 @@ public class AddSubkeyDialogFragment extends DialogFragment { mFlagAuthenticate.setChecked(false); mFlagAuthenticate.setEnabled(false); break; + case ECDSA: + mKeySizeRow.setVisibility(View.GONE); + mCurveRow.setVisibility(View.VISIBLE); + mCustomKeyInfoTextView.setText(""); + // allowed flags: + mFlagCertify.setEnabled(mWillBeMasterKey); + mFlagCertify.setChecked(mWillBeMasterKey); + mFlagSign.setEnabled(true); + mFlagSign.setChecked(!mWillBeMasterKey); + mFlagEncrypt.setEnabled(false); + mFlagEncrypt.setChecked(false); + mFlagAuthenticate.setEnabled(true); + mFlagAuthenticate.setChecked(false); + break; + case ECDH: + mKeySizeRow.setVisibility(View.GONE); + mCurveRow.setVisibility(View.VISIBLE); + mCustomKeyInfoTextView.setText(""); + // allowed flags: + mFlagCertify.setChecked(false); + mFlagCertify.setEnabled(false); + mFlagSign.setChecked(false); + mFlagSign.setEnabled(false); + mFlagEncrypt.setChecked(true); + mFlagEncrypt.setEnabled(true); + mFlagAuthenticate.setChecked(false); + mFlagAuthenticate.setEnabled(false); + break; } keySizeAdapter.notifyDataSetChanged(); - // when switching algorithm, try to select same key length as before - for (int i = 0; i < keySizeAdapter.getCount(); i++) { - if (selectedItem.equals(keySizeAdapter.getItem(i))) { - mKeySizeSpinner.setSelection(i); - break; - } - } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java index 70c7d80fe..48f10d4b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java @@ -17,21 +17,16 @@ package org.sufficientlysecure.keychain.util; -public class Choice { +public class Choice { private String mName; - private int mId; + private E mId; - public Choice() { - mId = -1; - mName = ""; - } - - public Choice(int id, String name) { + public Choice(E id, String name) { mId = id; mName = name; } - public int getId() { + public E getId() { return mId; } -- cgit v1.2.3 From 86a05033aedc965c1842db45094c744094a906af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 27 Aug 2014 13:54:33 +0200 Subject: Cleanup FoldableLinearLayout --- .../keychain/ui/widget/FoldableLinearLayout.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java index 31e01a7fb..b456b61ab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java @@ -24,7 +24,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -38,9 +38,7 @@ import org.sufficientlysecure.keychain.R; android:layout_width="wrap_content" android:layout_height="wrap_content" custom:foldedLabel="@string/TEXT_TO_DISPLAY_WHEN_FOLDED" - custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED" - custom:foldedIcon="ICON_NAME_FROM_FontAwesomeText_TO_USE_WHEN_FOLDED" - custom:unFoldedIcon="ICON_NAME_FROM_FontAwesomeText_TO_USE_WHEN_UNFOLDED"> + custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED"> @@ -49,7 +47,7 @@ import org.sufficientlysecure.keychain.R; */ public class FoldableLinearLayout extends LinearLayout { - private ImageButton mFoldableIcon; + private ImageView mFoldableIcon; private boolean mFolded; private boolean mHasMigrated = false; private Integer mShortAnimationDuration = null; @@ -139,7 +137,7 @@ public class FoldableLinearLayout extends LinearLayout { } private void initialiseInnerViews() { - mFoldableIcon = (ImageButton) mFoldableLayout.findViewById(R.id.foldableIcon); + mFoldableIcon = (ImageView) mFoldableLayout.findViewById(R.id.foldableIcon); mFoldableIcon.setImageResource(R.drawable.ic_action_expand); mFoldableTextView = (TextView) mFoldableLayout.findViewById(R.id.foldableText); mFoldableTextView.setText(mFoldedLabel); -- cgit v1.2.3 From 12a5b2174f79d93e8531fa4e0b3fc0def3796ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 27 Aug 2014 14:12:59 +0200 Subject: Abort import of pubkeys where secret keys exist but new pubkey has more subkeys, fix #696 --- .../keychain/pgp/UncachedKeyRing.java | 41 +++++++++++++++++----- .../keychain/service/OperationResultParcel.java | 1 + 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index caacb948e..424420e72 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -485,6 +485,10 @@ public class UncachedKeyRing { // Replace modified key in the keyring ring = replacePublicKey(ring, modified); + if (ring == null) { + log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + return null; + } indent -= 1; } @@ -652,6 +656,10 @@ public class UncachedKeyRing { } // replace pubkey in keyring ring = replacePublicKey(ring, modified); + if (ring == null) { + log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + return null; + } indent -= 1; } @@ -741,6 +749,10 @@ public class UncachedKeyRing { } else { // otherwise, just insert the public key result = replacePublicKey(result, key); + if (result == null) { + log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + return null; + } } continue; } @@ -769,6 +781,10 @@ public class UncachedKeyRing { if (!key.isMasterKey()) { if (modified != resultKey) { result = replacePublicKey(result, modified); + if (result == null) { + log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + return null; + } } continue; } @@ -793,6 +809,10 @@ public class UncachedKeyRing { // If anything changed, save the updated (sub)key if (modified != resultKey) { result = replacePublicKey(result, modified); + if (result == null) { + log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + return null; + } } } @@ -838,16 +858,19 @@ public class UncachedKeyRing { */ private static PGPKeyRing replacePublicKey(PGPKeyRing ring, PGPPublicKey key) { if (ring instanceof PGPPublicKeyRing) { - return PGPPublicKeyRing.insertPublicKey((PGPPublicKeyRing) ring, key); - } - PGPSecretKeyRing secRing = (PGPSecretKeyRing) ring; - PGPSecretKey sKey = secRing.getSecretKey(key.getKeyID()); - // TODO generate secret key with S2K dummy, if none exists! for now, just die. - if (sKey == null) { - throw new RuntimeException("dummy secret key generation not yet implemented"); + PGPPublicKeyRing pubRing = (PGPPublicKeyRing) ring; + return PGPPublicKeyRing.insertPublicKey(pubRing, key); + } else { + PGPSecretKeyRing secRing = (PGPSecretKeyRing) ring; + PGPSecretKey sKey = secRing.getSecretKey(key.getKeyID()); + // TODO generate secret key with S2K dummy, if none exists! + if (sKey == null) { + Log.e(Constants.TAG, "dummy secret key generation not yet implemented"); + return null; + } + sKey = PGPSecretKey.replacePublicKey(sKey, key); + return PGPSecretKeyRing.insertSecretKey(secRing, sKey); } - sKey = PGPSecretKey.replacePublicKey(sKey, key); - return PGPSecretKeyRing.insertSecretKey(secRing, sKey); } /** This method removes a subkey in a keyring. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 886f77068..ddc456e34 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -339,6 +339,7 @@ public class OperationResultParcel implements Parcelable { MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey), MSG_MG_FOUND_NEW (R.string.msg_mg_found_new), MSG_MG_UNCHANGED (R.string.msg_mg_unchanged), + MSG_MG_NO_SECRET_KEYRING (R.string.msg_mg_no_secret_keyring), // secret key create MSG_CR (R.string.msg_cr), -- cgit v1.2.3 From cb2eb8aca2e7aab6243fd3e1a3313c941e3f1998 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 Aug 2014 15:42:09 +0200 Subject: small language fixes for previous commit --- .../sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 15 +++++++-------- .../keychain/service/OperationResultParcel.java | 6 +++--- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 424420e72..65a2fe4a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -37,7 +37,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; -import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -486,7 +485,7 @@ public class UncachedKeyRing { // Replace modified key in the keyring ring = replacePublicKey(ring, modified); if (ring == null) { - log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_SECRET_DUMMY, indent); return null; } indent -= 1; @@ -657,7 +656,7 @@ public class UncachedKeyRing { // replace pubkey in keyring ring = replacePublicKey(ring, modified); if (ring == null) { - log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_SECRET_DUMMY, indent); return null; } indent -= 1; @@ -702,7 +701,7 @@ public class UncachedKeyRing { if (getMasterKeyId() != masterKeyId || !Arrays.equals(getFingerprint(), other.getFingerprint())) { - log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_HETEROGENEOUS, indent); return null; } @@ -750,7 +749,7 @@ public class UncachedKeyRing { // otherwise, just insert the public key result = replacePublicKey(result, key); if (result == null) { - log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_SECRET_DUMMY, indent); return null; } } @@ -782,7 +781,7 @@ public class UncachedKeyRing { if (modified != resultKey) { result = replacePublicKey(result, modified); if (result == null) { - log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_SECRET_DUMMY, indent); return null; } } @@ -810,7 +809,7 @@ public class UncachedKeyRing { if (modified != resultKey) { result = replacePublicKey(result, modified); if (result == null) { - log.add(LogLevel.ERROR, LogType.MSG_MG_NO_SECRET_KEYRING, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_SECRET_DUMMY, indent); return null; } } @@ -827,7 +826,7 @@ public class UncachedKeyRing { return new UncachedKeyRing(result); } catch (IOException e) { - log.add(LogLevel.ERROR, LogType.MSG_MG_FATAL_ENCODE, indent); + log.add(LogLevel.ERROR, LogType.MSG_MG_ERROR_ENCODE, indent); return null; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index ddc456e34..72cac4856 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -332,14 +332,14 @@ public class OperationResultParcel implements Parcelable { // keyring consolidation + MSG_MG_ERROR_SECRET_DUMMY(R.string.msg_mg_error_secret_dummy), + MSG_MG_ERROR_ENCODE(R.string.msg_mg_error_encode), + MSG_MG_ERROR_HETEROGENEOUS(R.string.msg_mg_error_heterogeneous), MSG_MG_PUBLIC (R.string.msg_mg_public), MSG_MG_SECRET (R.string.msg_mg_secret), - MSG_MG_FATAL_ENCODE (R.string.msg_mg_fatal_encode), - MSG_MG_HETEROGENEOUS (R.string.msg_mg_heterogeneous), MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey), MSG_MG_FOUND_NEW (R.string.msg_mg_found_new), MSG_MG_UNCHANGED (R.string.msg_mg_unchanged), - MSG_MG_NO_SECRET_KEYRING (R.string.msg_mg_no_secret_keyring), // secret key create MSG_CR (R.string.msg_cr), -- cgit v1.2.3 From d795f8d4e240877861ab993608fb7f5aed0a2042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 27 Aug 2014 19:28:33 +0200 Subject: Strip out duplicate user ids --- .../sufficientlysecure/keychain/pgp/UncachedKeyRing.java | 16 +++++++++++++--- .../keychain/service/OperationResultParcel.java | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 424420e72..9fa737be4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -37,7 +37,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; -import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -46,6 +45,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Date; @@ -339,7 +339,17 @@ public class UncachedKeyRing { } } + ArrayList processedUserIds = new ArrayList(); for (String userId : new IterableIterator(masterKey.getUserIDs())) { + // check for duplicate user ids + if (processedUserIds.contains(userId)) { + log.add(LogLevel.WARN, LogType.MSG_KC_UID_DUP, + indent, userId); + // strip out the first found user id with this name + modified = PGPPublicKey.removeCertification(modified, userId); + } + processedUserIds.add(userId); + PGPSignature selfCert = null; revocation = null; @@ -416,13 +426,13 @@ public class UncachedKeyRing { if (selfCert == null) { selfCert = zert; } else if (selfCert.getCreationTime().before(cert.getCreationTime())) { - log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP, + log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_CERT_DUP, indent, userId); modified = PGPPublicKey.removeCertification(modified, userId, selfCert); redundantCerts += 1; selfCert = zert; } else { - log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_DUP, + log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_CERT_DUP, indent, userId); modified = PGPPublicKey.removeCertification(modified, userId, zert); redundantCerts += 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index ddc456e34..a08ee3091 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -323,6 +323,7 @@ public class OperationResultParcel implements Parcelable { MSG_KC_UID_BAD_TIME (R.string.msg_kc_uid_bad_time), MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type), MSG_KC_UID_BAD (R.string.msg_kc_uid_bad), + MSG_KC_UID_CERT_DUP (R.string.msg_kc_uid_cert_dup), MSG_KC_UID_DUP (R.string.msg_kc_uid_dup), MSG_KC_UID_FOREIGN (R.string.msg_kc_uid_foreign), MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert), -- cgit v1.2.3 From 4aeacd5b51bed1358b2775aff6b2fc2a6d218165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 28 Aug 2014 10:40:11 +0200 Subject: Fix NullPointerException in ImportKeysActivity --- .../java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 18f805360..96fa11363 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -288,7 +288,9 @@ public class ImportKeysActivity extends ActionBarActivity { @Override public void onPageSelected(int position) { // cancel loader and clear list - mListFragment.destroyLoader(); + if (mListFragment != null) { + mListFragment.destroyLoader(); + } } @Override -- cgit v1.2.3