diff --git a/AndroidManifest.xml b/AndroidManifest.xml index bab42ab18..29ec741f9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -115,6 +115,11 @@ android:label="@string/title_mailInbox" android:configChanges="keyboardHidden|orientation|keyboard"/> + + diff --git a/res/layout/encrypt_file.xml b/res/layout/encrypt_file.xml index ce685e644..3ea2f06ac 100644 --- a/res/layout/encrypt_file.xml +++ b/res/layout/encrypt_file.xml @@ -65,14 +65,15 @@ android:layout_height="wrap_content" android:orientation="horizontal"> - + - + - + - + - + diff --git a/res/layout/preferences.xml b/res/layout/preferences.xml new file mode 100644 index 000000000..0bf579099 --- /dev/null +++ b/res/layout/preferences.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 0bbf7fa2e..e820dc16e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -28,6 +28,7 @@ Authentification Create Key Edit Key + Preferences User IDs Keys @@ -49,6 +50,7 @@ Add GMail Account Manage Public Keys Manage Secret Keys + Settings Select 1 Selected @@ -65,6 +67,11 @@ Public Key(s) Use Pass Phrase + Encryption Algorithm + Hash Algorithm + + Defaults + Sign only Encrypt only Sign and Encrypt diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index 16c743676..8596bdafc 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -1175,7 +1175,7 @@ public class Apg { long encryptionKeyIds[], long signatureKeyId, String signaturePassPhrase, ProgressDialogUpdater progress, - int symmetricAlgorithm, + int symmetricAlgorithm, int hashAlgorithm, String passPhrase) throws IOException, GeneralException, PGPException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException { @@ -1251,7 +1251,7 @@ public class Apg { progress.setProgress("preparing signature...", 30, 100); signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(), - HashAlgorithmTags.SHA1, + hashAlgorithm, new BouncyCastleProvider()); signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); String userId = getMainUserId(getMasterKey(signingKeyRing)); diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java index 3365270dd..01415734b 100644 --- a/src/org/thialfihar/android/apg/BaseActivity.java +++ b/src/org/thialfihar/android/apg/BaseActivity.java @@ -16,12 +16,16 @@ package org.thialfihar.android.apg; +import org.bouncycastle2.bcpg.HashAlgorithmTags; +import org.bouncycastle2.openpgp.PGPEncryptedData; + import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -34,6 +38,7 @@ public class BaseActivity extends Activity private Thread mRunningThread = null; private long mSecretKeyId = 0; + protected static SharedPreferences mPreferences = null; private Handler mHandler = new Handler() { @Override @@ -46,6 +51,9 @@ public class BaseActivity extends Activity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (mPreferences == null) { + mPreferences = getPreferences(MODE_PRIVATE); + } Apg.initialize(this); } @@ -245,4 +253,46 @@ public class BaseActivity extends Activity public long getSecretKeyId() { return mSecretKeyId; } + + public int getDefaultEncryptionAlgorithm() { + return mPreferences.getInt(Constants.pref.default_encryption_algorithm, + PGPEncryptedData.AES_256); + } + + public void setDefaultEncryptionAlgorithm(int value) { + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putInt(Constants.pref.default_encryption_algorithm, value); + editor.commit(); + } + + public int getDefaultHashAlgorithm() { + return mPreferences.getInt(Constants.pref.default_hash_algorithm, + HashAlgorithmTags.SHA256); + } + + public void setDefaultHashAlgorithm(int value) { + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putInt(Constants.pref.default_hash_algorithm, value); + editor.commit(); + } + + public boolean getDefaultAsciiArmour() { + return mPreferences.getBoolean(Constants.pref.default_ascii_armour, false); + } + + public void setDefaultAsciiArmour(boolean value) { + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(Constants.pref.default_ascii_armour, value); + editor.commit(); + } + + public boolean hasSeenChangeLog() { + return mPreferences.getBoolean(Constants.pref.has_seen_change_log, false); + } + + public void setHasSeenChangeLog(boolean value) { + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(Constants.pref.has_seen_change_log, value); + editor.commit(); + } } diff --git a/src/org/thialfihar/android/apg/Constants.java b/src/org/thialfihar/android/apg/Constants.java index fdd71578e..7ddc13985 100644 --- a/src/org/thialfihar/android/apg/Constants.java +++ b/src/org/thialfihar/android/apg/Constants.java @@ -25,5 +25,8 @@ public final class Constants { public static final class pref { public static final String has_seen_change_log = "seenChangeLogDialog" + Apg.VERSION; + public static final String default_encryption_algorithm = "defaultEncryptionAlgorithm"; + public static final String default_hash_algorithm = "defaultHashAlgorithm"; + public static final String default_ascii_armour = "defaultAsciiArmour"; } } diff --git a/src/org/thialfihar/android/apg/EncryptFileActivity.java b/src/org/thialfihar/android/apg/EncryptFileActivity.java index 9ee49f9b5..0c5ce20c0 100644 --- a/src/org/thialfihar/android/apg/EncryptFileActivity.java +++ b/src/org/thialfihar/android/apg/EncryptFileActivity.java @@ -81,6 +81,7 @@ public class EncryptFileActivity extends BaseActivity { setContentView(R.layout.encrypt_file); mAsciiArmour = (CheckBox) findViewById(R.id.ascii_armour); + mAsciiArmour.setChecked(getDefaultAsciiArmour()); // asymmetric tab mSelectKeysButton = (Button) findViewById(R.id.btn_selectEncryptKeys); @@ -138,7 +139,7 @@ public class EncryptFileActivity extends BaseActivity { adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mAlgorithm.setAdapter(adapter); for (int i = 0; i < choices.length; ++i) { - if (choices[i].getId() == PGPEncryptedData.AES_256) { + if (choices[i].getId() == getDefaultEncryptionAlgorithm()) { mAlgorithm.setSelection(i); break; } @@ -331,6 +332,7 @@ public class EncryptFileActivity extends BaseActivity { mEncryptionKeyIds, getSecretKeyId(), Apg.getPassPhrase(), this, ((Choice) mAlgorithm.getSelectedItem()).getId(), + getDefaultHashAlgorithm(), passPhrase); out.close(); diff --git a/src/org/thialfihar/android/apg/EncryptMessageActivity.java b/src/org/thialfihar/android/apg/EncryptMessageActivity.java index f03e6ea09..da49bf26b 100644 --- a/src/org/thialfihar/android/apg/EncryptMessageActivity.java +++ b/src/org/thialfihar/android/apg/EncryptMessageActivity.java @@ -25,7 +25,6 @@ import java.security.SignatureException; import java.util.Vector; import org.bouncycastle2.bcpg.HashAlgorithmTags; -import org.bouncycastle2.openpgp.PGPEncryptedData; import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPPublicKey; import org.bouncycastle2.openpgp.PGPPublicKeyRing; @@ -202,10 +201,11 @@ public class EncryptMessageActivity extends BaseActivity { if (encryptIt) { Apg.encrypt(in, out, true, mEncryptionKeyIds, getSecretKeyId(), Apg.getPassPhrase(), this, - PGPEncryptedData.AES_256, null); + getDefaultEncryptionAlgorithm(), getDefaultHashAlgorithm(), + null); } else { Apg.signText(in, out, getSecretKeyId(), - Apg.getPassPhrase(), HashAlgorithmTags.SHA256, this); + Apg.getPassPhrase(), getDefaultHashAlgorithm(), this); } data.putString("message", new String(out.toByteArray())); } catch (IOException e) { diff --git a/src/org/thialfihar/android/apg/Id.java b/src/org/thialfihar/android/apg/Id.java index c96b4ccb7..b0c8368e6 100644 --- a/src/org/thialfihar/android/apg/Id.java +++ b/src/org/thialfihar/android/apg/Id.java @@ -30,6 +30,7 @@ public final class Id { public static final int manage_secret_keys = 0x21070005; public static final int import_keys = 0x21070006; public static final int export_keys = 0x21070007; + public static final int preferences = 0x21070008; } } diff --git a/src/org/thialfihar/android/apg/MainActivity.java b/src/org/thialfihar/android/apg/MainActivity.java index 30551c4ad..baa875ee2 100644 --- a/src/org/thialfihar/android/apg/MainActivity.java +++ b/src/org/thialfihar/android/apg/MainActivity.java @@ -67,28 +67,28 @@ public class MainActivity extends BaseActivity { encryptMessageButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - startEncryptMessageActivity(); + startActivity(new Intent(MainActivity.this, EncryptMessageActivity.class)); } }); decryptMessageButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - startDecryptMessageActivity(); + startActivity(new Intent(MainActivity.this, DecryptMessageActivity.class)); } }); encryptFileButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - startEncryptFileActivity(); + startActivity(new Intent(MainActivity.this, EncryptFileActivity.class)); } }); decryptFileButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - startDecryptFileActivity(); + startActivity(new Intent(MainActivity.this, DecryptFileActivity.class)); } }); @@ -105,14 +105,14 @@ public class MainActivity extends BaseActivity { cursor.moveToFirst(); int nameIndex = cursor.getColumnIndex(Accounts.NAME); String accountName = cursor.getString(nameIndex); - startMailListActivity(accountName); + startActivity(new Intent(MainActivity.this, MailListActivity.class) + .putExtra("account", accountName)); } } }); registerForContextMenu(mAccounts); - SharedPreferences prefs = getPreferences(MODE_PRIVATE); - if (!prefs.getBoolean(Constants.pref.has_seen_change_log, false)) { + if (!hasSeenChangeLog()) { showDialog(Id.dialog.change_log); } } @@ -248,10 +248,7 @@ public class MainActivity extends BaseActivity { new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainActivity.this.removeDialog(Id.dialog.change_log); - SharedPreferences prefs = getPreferences(MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(Constants.pref.has_seen_change_log, true); - editor.commit(); + setHasSeenChangeLog(true); } }); @@ -268,13 +265,15 @@ public class MainActivity extends BaseActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, Id.menu.option.manage_public_keys, 0, R.string.menu_managePublicKeys) + menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences) + .setIcon(android.R.drawable.ic_menu_preferences); + menu.add(1, Id.menu.option.manage_public_keys, 1, R.string.menu_managePublicKeys) .setIcon(android.R.drawable.ic_menu_manage); - menu.add(0, Id.menu.option.manage_secret_keys, 1, R.string.menu_manageSecretKeys) + menu.add(1, Id.menu.option.manage_secret_keys, 2, R.string.menu_manageSecretKeys) .setIcon(android.R.drawable.ic_menu_manage); - menu.add(1, Id.menu.option.create, 2, R.string.menu_addAccount) + menu.add(2, Id.menu.option.create, 3, R.string.menu_addAccount) .setIcon(android.R.drawable.ic_menu_add); - menu.add(1, Id.menu.option.about, 3, R.string.menu_about) + menu.add(2, Id.menu.option.about, 4, R.string.menu_about) .setIcon(android.R.drawable.ic_menu_info_details); return true; } @@ -293,12 +292,17 @@ public class MainActivity extends BaseActivity { } case Id.menu.option.manage_public_keys: { - startPublicKeyManager(); + startActivity(new Intent(this, PublicKeyListActivity.class)); return true; } case Id.menu.option.manage_secret_keys: { - startSecretKeyManager(); + startActivity(new Intent(this, SecretKeyListActivity.class)); + return true; + } + + case Id.menu.option.preferences: { + startActivity(new Intent(this, PreferencesActivity.class)); return true; } @@ -338,33 +342,6 @@ public class MainActivity extends BaseActivity { } } - public void startPublicKeyManager() { - startActivity(new Intent(this, PublicKeyListActivity.class)); - } - - public void startSecretKeyManager() { - startActivity(new Intent(this, SecretKeyListActivity.class)); - } - - public void startEncryptMessageActivity() { - startActivity(new Intent(this, EncryptMessageActivity.class)); - } - - public void startDecryptMessageActivity() { - startActivity(new Intent(this, DecryptMessageActivity.class)); - } - - public void startEncryptFileActivity() { - startActivity(new Intent(this, EncryptFileActivity.class)); - } - - public void startDecryptFileActivity() { - startActivity(new Intent(this, DecryptFileActivity.class)); - } - - public void startMailListActivity(String account) { - startActivity(new Intent(this, MailListActivity.class).putExtra("account", account)); - } private static class AccountListAdapter extends CursorAdapter { private LayoutInflater minflater; diff --git a/src/org/thialfihar/android/apg/PreferencesActivity.java b/src/org/thialfihar/android/apg/PreferencesActivity.java new file mode 100644 index 000000000..12deb11fe --- /dev/null +++ b/src/org/thialfihar/android/apg/PreferencesActivity.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010 Thialfihar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thialfihar.android.apg; + +import org.bouncycastle2.bcpg.HashAlgorithmTags; +import org.bouncycastle2.openpgp.PGPEncryptedData; +import org.thialfihar.android.apg.utils.Choice; + +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.Spinner; +import android.widget.AdapterView.OnItemSelectedListener; + +public class PreferencesActivity extends BaseActivity { + private Spinner mEncryptionAlgorithm = null; + private Spinner mHashAlgorithm = null; + private CheckBox mAsciiArmour = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.preferences); + + mEncryptionAlgorithm = (Spinner) findViewById(R.id.encryption_algorithm); + mHashAlgorithm = (Spinner) findViewById(R.id.hash_algorithm); + mAsciiArmour = (CheckBox) findViewById(R.id.ascii_armour); + + mAsciiArmour.setChecked(getDefaultAsciiArmour()); + + Choice choices[] = { + new Choice(PGPEncryptedData.AES_128, "AES 128"), + new Choice(PGPEncryptedData.AES_192, "AES 192"), + new Choice(PGPEncryptedData.AES_256, "AES 256"), + new Choice(PGPEncryptedData.BLOWFISH, "Blowfish"), + new Choice(PGPEncryptedData.TWOFISH, "Twofish"), + new Choice(PGPEncryptedData.CAST5, "CAST5"), + new Choice(PGPEncryptedData.DES, "DES"), + new Choice(PGPEncryptedData.TRIPLE_DES, "Triple DES"), + new Choice(PGPEncryptedData.IDEA, "IDEA"), + }; + ArrayAdapter adapter = + new ArrayAdapter(this, android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mEncryptionAlgorithm.setAdapter(adapter); + + for (int i = 0; i < choices.length; ++i) { + if (choices[i].getId() == getDefaultEncryptionAlgorithm()) { + mEncryptionAlgorithm.setSelection(i); + break; + } + } + + mEncryptionAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapter, View view, int index, long id) { + setDefaultEncryptionAlgorithm(((Choice) mEncryptionAlgorithm.getSelectedItem()).getId()); + } + + @Override + public void onNothingSelected(AdapterView adapter) { + // nothing to do + } + }); + + Choice choices2[] = { + new Choice(HashAlgorithmTags.MD5, "MD5"), + new Choice(HashAlgorithmTags.RIPEMD160, "RIPEMD160"), + new Choice(HashAlgorithmTags.SHA1, "SHA1"), + new Choice(HashAlgorithmTags.SHA224, "SHA224"), + new Choice(HashAlgorithmTags.SHA256, "SHA256"), + new Choice(HashAlgorithmTags.SHA384, "SHA384"), + new Choice(HashAlgorithmTags.SHA512, "SHA512"), + }; + adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, choices2); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mHashAlgorithm.setAdapter(adapter); + + for (int i = 0; i < choices2.length; ++i) { + if (choices2[i].getId() == getDefaultHashAlgorithm()) { + mHashAlgorithm.setSelection(i); + break; + } + } + + mHashAlgorithm.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapter, View view, int index, long id) { + setDefaultHashAlgorithm(((Choice) mHashAlgorithm.getSelectedItem()).getId()); + } + + @Override + public void onNothingSelected(AdapterView adapter) { + // nothing to do + } + }); + + mAsciiArmour.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + setDefaultAsciiArmour(mAsciiArmour.isChecked()); + } + }); + } +} +