aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-04-08 10:00:53 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2014-04-08 10:00:53 +0200
commit02549bd43910adbda7bcce0d706c60484b6890f0 (patch)
tree8942b1cb50d1492c53ba6651b7017bac54a26cf4
parent97ecf25cb42e5d438f0e57061cdbd8b8a8122195 (diff)
parente76fc97dd6b137b50f2df9615f857abe378a3965 (diff)
downloadopen-keychain-02549bd43910adbda7bcce0d706c60484b6890f0.tar.gz
open-keychain-02549bd43910adbda7bcce0d706c60484b6890f0.tar.bz2
open-keychain-02549bd43910adbda7bcce0d706c60484b6890f0.zip
Merge pull request #536 from gogowitczak/custom-key-length
Added possibility to enter custom key length.
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java151
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_dialog.xml18
-rw-r--r--OpenKeychain/src/main/res/values/arrays.xml2
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml3
4 files changed, 152 insertions, 22 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
index ad558a81e..78223379b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
@@ -23,11 +23,15 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.EditText;
import android.widget.Spinner;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.Choice;
@@ -45,6 +49,10 @@ public class CreateKeyDialogFragment extends DialogFragment {
private int mNewKeySize;
private Choice mNewKeyAlgorithmChoice;
private OnAlgorithmSelectedListener mAlgorithmSelectedListener;
+ private Spinner mAlgorithmSpinner;
+ private Spinner mKeySizeSpinner;
+ private TextView mCustomKeyTextView;
+ private EditText mCustomKeyEditText;
public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) {
mAlgorithmSelectedListener = listener;
@@ -77,7 +85,7 @@ public class CreateKeyDialogFragment extends DialogFragment {
boolean wouldBeMasterKey = (childCount == 0);
- final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
+ mAlgorithmSpinner = (Spinner) view.findViewById(R.id.create_key_algorithm);
ArrayList<Choice> choices = new ArrayList<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(
R.string.dsa)));
@@ -92,38 +100,53 @@ public class CreateKeyDialogFragment extends DialogFragment {
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(context,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- algorithm.setAdapter(adapter);
+ mAlgorithmSpinner.setAdapter(adapter);
// make RSA the default
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
- algorithm.setSelection(i);
+ mAlgorithmSpinner.setSelection(i);
break;
}
}
- final Spinner keySize = (Spinner) view.findViewById(R.id.create_key_size);
+ mKeySizeSpinner = (Spinner) view.findViewById(R.id.create_key_size);
ArrayAdapter<CharSequence> keySizeAdapter = ArrayAdapter.createFromResource(
context, R.array.key_size_spinner_values,
android.R.layout.simple_spinner_item);
keySizeAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- keySize.setAdapter(keySizeAdapter);
- keySize.setSelection(3); // Default to 4096 for the key length
+ mKeySizeSpinner.setAdapter(keySizeAdapter);
+ mKeySizeSpinner.setSelection(3); // Default to 4096 for the key length
+
+ mCustomKeyTextView = (TextView) view.findViewById(R.id.custom_key_size_label);
+ mCustomKeyEditText = (EditText) view.findViewById(R.id.custom_key_size_input);
+
+ final AdapterView.OnItemSelectedListener customKeySelectedLisener = new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ final String selectedItemString = (String) parent.getSelectedItem();
+ final String customLengthString = getResources().getString(R.string.key_size_custom);
+ final boolean customSelected = customLengthString.equals(selectedItemString);
+ final int visibility = customSelected ? View.VISIBLE : View.GONE;
+ mCustomKeyEditText.setVisibility(visibility);
+ mCustomKeyTextView.setVisibility(visibility);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ };
+
dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
- try {
- final String selectedItem = (String) keySize.getSelectedItem();
- mNewKeySize = Integer.parseInt(selectedItem);
- } catch (NumberFormatException e) {
- mNewKeySize = 0;
- }
-
- mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
+ mNewKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem();
+ mNewKeySize = getProperKeyLength(mNewKeyAlgorithmChoice.getId(), getSelectedKeyLength());
mAlgorithmSelectedListener.onAlgorithmSelected(mNewKeyAlgorithmChoice, mNewKeySize);
}
- });
+ }
+ );
dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel,
@@ -138,11 +161,10 @@ public class CreateKeyDialogFragment extends DialogFragment {
final AdapterView.OnItemSelectedListener weakRsaListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- final Choice selectedAlgorithm = (Choice) algorithm.getSelectedItem();
- final int selectedKeySize = Integer.parseInt((String) keySize.getSelectedItem());
- final boolean isWeakRsa = (selectedAlgorithm.getId() == Id.choice.algorithm.rsa &&
- selectedKeySize <= 1024);
- alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(!isWeakRsa);
+ if (mKeySizeSpinner == parent) {
+ customKeySelectedLisener.onItemSelected(parent, view, position, id);
+ }
+ setOkButtonAvailability(alertDialog);
}
@Override
@@ -150,10 +172,95 @@ public class CreateKeyDialogFragment extends DialogFragment {
}
};
- keySize.setOnItemSelectedListener(weakRsaListener);
- algorithm.setOnItemSelectedListener(weakRsaListener);
+ mCustomKeyEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ setOkButtonAvailability(alertDialog);
+ }
+ });
+
+ mKeySizeSpinner.setOnItemSelectedListener(weakRsaListener);
+ mAlgorithmSpinner.setOnItemSelectedListener(weakRsaListener);
return alertDialog;
}
+ private int getSelectedKeyLength() {
+ final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem();
+ final String customLengthString = getResources().getString(R.string.key_size_custom);
+ final boolean customSelected = customLengthString.equals(selectedItemString);
+ String keyLengthString = customSelected ? mCustomKeyEditText.getText().toString() : selectedItemString;
+ int keySize = 0;
+ try {
+ keySize = Integer.parseInt(keyLengthString);
+ } catch (NumberFormatException e) {
+ keySize = 0;
+ }
+ return keySize;
+ }
+
+ /**
+ * <h3>RSA</h3>
+ * <p>for RSA algorithm, key length must be greater than 1024 (according to
+ * <a href="https://github.com/open-keychain/open-keychain/issues/102">#102</a>). Possibility to generate keys bigger
+ * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check
+ * <a href="http://www.javamex.com/tutorials/cryptography/rsa_key_length.shtml">RSA key length plot</a> and
+ * <a href="http://www.keylength.com/">Cryptographic Key Length Recommendation</a>). Also, key length must be a
+ * multiplicity of 8.</p>
+ * <h3>ElGamal</h3>
+ * <p>For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.</p>
+ * <h3>DSA</h3>
+ * <p>For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.</p>
+ *
+ * @return correct key length, according to SpongyCastle specification. Returns <code>-1</code>, if key length is
+ * inappropriate.
+ */
+ private int getProperKeyLength(int algorithmId, int currentKeyLength) {
+ final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192};
+ int properKeyLength = -1;
+ switch (algorithmId) {
+ case Id.choice.algorithm.rsa:
+ if (currentKeyLength > 1024 && currentKeyLength <= 8192) {
+ properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8);
+ }
+ break;
+ case Id.choice.algorithm.elgamal:
+ int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length];
+ for (int i = 0; i < elGamalSupportedLengths.length; i++) {
+ elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength);
+ }
+ int minimalValue = Integer.MAX_VALUE;
+ int minimalIndex = -1;
+ for (int i = 0; i < elGammalKeyDiff.length; i++) {
+ if (elGammalKeyDiff[i] <= minimalValue) {
+ minimalValue = elGammalKeyDiff[i];
+ minimalIndex = i;
+ }
+ }
+ properKeyLength = elGamalSupportedLengths[minimalIndex];
+ break;
+ case Id.choice.algorithm.dsa:
+ if (currentKeyLength >= 512 && currentKeyLength <= 1024) {
+ properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64);
+ }
+ break;
+ }
+ return properKeyLength;
+ }
+
+ 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);
+ }
+
}
diff --git a/OpenKeychain/src/main/res/layout/create_key_dialog.xml b/OpenKeychain/src/main/res/layout/create_key_dialog.xml
index 57a1b865f..da884ceb5 100644
--- a/OpenKeychain/src/main/res/layout/create_key_dialog.xml
+++ b/OpenKeychain/src/main/res/layout/create_key_dialog.xml
@@ -56,6 +56,24 @@
android:gravity="right"
android:padding="4dp" />
</TableRow>
+
+ <TextView
+ android:id="@+id/custom_key_size_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:padding="4dp"
+ android:text="@string/key_size_custom_info"
+ android:visibility="gone"/>
+
+ <EditText
+ android:id="@+id/custom_key_size_input"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="number"
+ android:visibility="gone"/>
+
</TableLayout>
</ScrollView> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/arrays.xml b/OpenKeychain/src/main/res/values/arrays.xml
index c84c2648d..b16973f90 100644
--- a/OpenKeychain/src/main/res/values/arrays.xml
+++ b/OpenKeychain/src/main/res/values/arrays.xml
@@ -34,6 +34,8 @@
<item>@string/key_size_1024</item>
<item>@string/key_size_2048</item>
<item>@string/key_size_4096</item>
+ <item>@string/key_size_8192</item>
+ <item>@string/key_size_custom</item>
</string-array>
<string-array name="import_action_list" translatable="false">
<item>@string/menu_import_from_key_server</item>
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 6c6d05103..c1d62fd52 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -378,6 +378,9 @@
<string name="key_size_1024">1024</string>
<string name="key_size_2048">2048</string>
<string name="key_size_4096">4096</string>
+ <string name="key_size_8192">8192</string>
+ <string name="key_size_custom">Custom key size</string>
+ <string name="key_size_custom_info">Type custom key length (in bits):</string>
<!-- compression -->
<string name="compression_fast">fast</string>