[seahorse] SSH: key generate: add a widget for key lengths.



commit f9acfe53d7a3031e576a8b51246b363492c6690b
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Mar 7 18:27:34 2018 +0100

    SSH: key generate: add a widget for key lengths.
    
    Since the different types of key types require different handling, add a
    very basic widget which handles this.

 po/POTFILES.in               |    1 +
 po/POTFILES.skip             |    1 +
 ssh/generate.vala            |   29 +++++---------
 ssh/key-length-chooser.vala  |   87 ++++++++++++++++++++++++++++++++++++++++++
 ssh/meson.build              |    1 +
 ssh/operation.vala           |    9 +---
 ssh/seahorse-ssh-generate.ui |   37 +-----------------
 7 files changed, 105 insertions(+), 60 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7c3be1e..0ff1206 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -103,6 +103,7 @@ ssh/errors.vala
 ssh/exporter.vala
 ssh/generate.vala
 ssh/key-data.vala
+ssh/key-length-chooser.vala
 ssh/key-properties.vala
 ssh/key.vala
 ssh/operation.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 300652e..352b4f0 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -34,6 +34,7 @@ ssh/exporter.c
 ssh/generate.c
 ssh/key.c
 ssh/key-data.c
+ssh/key-length-chooser.c
 ssh/key-properties.c
 ssh/operation.c
 ssh/source.c
diff --git a/ssh/generate.vala b/ssh/generate.vala
index 6cb26e8..b5f2adb 100644
--- a/ssh/generate.vala
+++ b/ssh/generate.vala
@@ -30,7 +30,8 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
 
     private Source source;
 
-    private Gtk.SpinButton bits_spin_button;
+    private Gtk.Grid details_grid;
+    private KeyLengthChooser key_length_chooser;
     private Gtk.Entry email_entry;
     private Gtk.ComboBoxText algorithm_combo_box;
     private Gtk.Button create_with_setup_button;
@@ -46,7 +47,10 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
 
         load_ui();
 
-        // on_change() gets called, bits entry is setup
+        this.key_length_chooser = new KeyLengthChooser();
+        this.details_grid.attach(this.key_length_chooser, 1, 1);
+
+        // on_algo_changed() gets called, bits chooser is setup
         algorithm_combo_box.set_active(0);
     }
 
@@ -80,27 +84,21 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
         Gtk.Widget actions = (Gtk.Widget) builder.get_object("action_area");
         ((Gtk.Container)this.get_action_area()).add(actions);
 
-        this.bits_spin_button = (Gtk.SpinButton) builder.get_object("bits-spin-button");
+        this.details_grid = (Gtk.Grid) builder.get_object("details_grid");
         this.email_entry = (Gtk.Entry) builder.get_object("email-entry");
         this.algorithm_combo_box = (Gtk.ComboBoxText) builder.get_object("algorithm-combo-box");
         this.create_no_setup_button = (Gtk.Button) builder.get_object("create-no-setup");
         this.create_with_setup_button = (Gtk.Button) builder.get_object("create-with-setup");
 
         // Signals
-        this.algorithm_combo_box.changed.connect(on_change);
+        this.algorithm_combo_box.changed.connect(on_algo_changed);
         this.create_no_setup_button.clicked.connect((b) => create_key(false));
         this.create_with_setup_button.clicked.connect((b) => create_key(true));
     }
 
-    private void on_change(Gtk.ComboBox combo) {
+    private void on_algo_changed(Gtk.ComboBox combo) {
         string t = algorithm_combo_box.get_active_text();
-        if (Algorithm.from_string(t) == Algorithm.DSA) {
-           this.bits_spin_button.set_value(DEFAULT_DSA_SIZE);
-           this.bits_spin_button.sensitive = false;
-        } else {
-           this.bits_spin_button.set_value(DEFAULT_RSA_SIZE);
-           this.bits_spin_button.sensitive = true;
-        }
+        this.key_length_chooser.algorithm = Algorithm.from_string(t);
     }
 
     private void create_key(bool upload) {
@@ -112,12 +110,7 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
         Algorithm type = Algorithm.from_string(t);
         assert(type != Algorithm.UNKNOWN);
 
-        // The number of bits
-        uint bits = this.bits_spin_button.get_value_as_int();
-        if (bits < 512 || bits > 8192) {
-            message("Invalid key size: %s defaulting to 2048", t);
-            bits = 2048;
-        }
+        uint bits = this.key_length_chooser.get_length();
 
         // The filename
         string filename = this.source.new_filename_for_algorithm(type);
diff --git a/ssh/key-length-chooser.vala b/ssh/key-length-chooser.vala
new file mode 100644
index 0000000..1590b0b
--- /dev/null
+++ b/ssh/key-length-chooser.vala
@@ -0,0 +1,87 @@
+
+/**
+ * The KeyLengthChooser allows the user choose the amount of bits a key should
+ * have (i.e. the strength of a key). Since the several types of keys (see
+ * {@link Ssh.Algorithm}) all support several sizes in their own way (if at
+ * all even), we need to adjust the UI to the chosen type.
+ *
+ * Please also refer to the man pages of ssh-keygen to know why some
+ * some restrictions are added.
+ */
+public class Seahorse.Ssh.KeyLengthChooser : Gtk.Stack {
+
+    private Gtk.SpinButton spin_button;  // For RSA
+    private Gtk.ComboBoxText combobox;   // For ECDSA
+    private Gtk.Label not_supported;     // For DSA, ED25519 and unknowns
+
+    public Algorithm algorithm { get; set; }
+
+    public KeyLengthChooser(Algorithm algo = Algorithm.RSA) {
+        this.visible = true;
+
+        // RSA
+        var rsa_size_adj = new Gtk.Adjustment(2048, 1024, 8193, 256, 10, 1);
+        this.spin_button = new Gtk.SpinButton(rsa_size_adj, 1, 0);
+        add(this.spin_button);
+
+        // ECDSA
+        this.combobox = new Gtk.ComboBoxText();
+        this.combobox.append_text("256");
+        this.combobox.append_text("384");
+        this.combobox.append_text("521");
+        this.combobox.active = 0;
+        add(this.combobox);
+
+        // DSA, ED25519, and Unknown
+        this.not_supported = new Gtk.Label(null);
+        add(this.not_supported);
+
+        show_all();
+
+        // Now set the initial algorithm
+        this.notify["algorithm"].connect(on_algo_changed);
+        this.algorithm = algo;
+    }
+
+    /**
+     * Returns the chosen key length (in bits). In case of an unknown algorithm,
+     * it will return 0.
+     */
+    public int get_length () {
+        switch (this.algorithm) {
+            case Algorithm.RSA:
+                return this.spin_button.get_value_as_int();
+            case Algorithm.DSA:
+                return 1024;
+            case Algorithm.ECDSA:
+                return int.parse(this.combobox.get_active_text());
+            case Algorithm.ED25519:
+                return 256;
+        }
+
+        return 0;
+    }
+
+    private void on_algo_changed (GLib.Object src, ParamSpec pspec) {
+        switch (this.algorithm) {
+            case Algorithm.RSA:
+                this.visible_child = this.spin_button;
+                break;
+            case Algorithm.ECDSA:
+                this.visible_child = this.combobox;
+                break;
+            case Algorithm.DSA:
+                this.not_supported.label = _("1024 bits");
+                this.visible_child = this.not_supported;
+                break;
+            case Algorithm.ED25519:
+                this.not_supported.label = _("256 bits");
+                this.visible_child = this.not_supported;
+                break;
+            case Algorithm.UNKNOWN:
+                this.not_supported.label = _("Unknown key type!");
+                this.visible_child = this.not_supported;
+                break;
+        }
+    }
+}
diff --git a/ssh/meson.build b/ssh/meson.build
index efb0719..25a5722 100644
--- a/ssh/meson.build
+++ b/ssh/meson.build
@@ -7,6 +7,7 @@ ssh_sources = [
   'exporter.vala',
   'generate.vala',
   'key-data.vala',
+  'key-length-chooser.vala',
   'key-properties.vala',
   'key.vala',
   'operation.vala',
diff --git a/ssh/operation.vala b/ssh/operation.vala
index 174e91d..eeb7739 100644
--- a/ssh/operation.vala
+++ b/ssh/operation.vala
@@ -282,14 +282,11 @@ public class GenerateOperation : Operation {
 
         this.prompt_title = _("Passphrase for New Secure Shell Key");
 
-        string comment = escape_shell_arg(email);
         string algo = type.to_string().down();
+        string bits_str = (bits != 0)? "-b '%u'".printf(bits) : "";
+        string comment = escape_shell_arg(email);
 
-        // Default number of bits
-        if (bits == 0)
-            bits = 2048;
-
-        string cmd = "%s -b '%u' -t '%s' -C %s -f '%s'".printf(Config.SSH_KEYGEN_PATH, bits, algo, comment, 
filename);
+        string cmd = "%s %s -t '%s' -C %s -f '%s'".printf(Config.SSH_KEYGEN_PATH, bits_str, algo, comment, 
filename);
 
         yield operation_async(cmd, null, cancellable);
     }
diff --git a/ssh/seahorse-ssh-generate.ui b/ssh/seahorse-ssh-generate.ui
index 459f6f4..2230f0b 100644
--- a/ssh/seahorse-ssh-generate.ui
+++ b/ssh/seahorse-ssh-generate.ui
@@ -1,13 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="3.0"/>
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="lower">768</property>
-    <property name="upper">8192</property>
-    <property name="value">2048</property>
-    <property name="step_increment">256</property>
-    <property name="page_increment">10</property>
-  </object>
   <object class="GtkBox" id="ssh-generate">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -199,7 +192,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <child>
-                  <object class="GtkGrid" id="grid2">
+                  <object class="GtkGrid" id="details_grid">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="margin_left">20</property>
@@ -228,7 +221,6 @@
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">Key _Strength (bits):</property>
                         <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">bits-spin-button</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -266,33 +258,6 @@
                         <property name="height">1</property>
                       </packing>
                     </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="yalign">0</property>
-                        <property name="xscale">0</property>
-                        <property name="yscale">0</property>
-                        <child>
-                          <object class="GtkSpinButton" id="bits-spin-button">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">●</property>
-                            <property name="invisible_char_set">True</property>
-                            <property name="adjustment">adjustment1</property>
-                            <property name="climb_rate">1</property>
-                            <property name="numeric">True</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
                   </object>
                 </child>
                 <child type="label">


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]