[epiphany/wip/ephy-sync] Implement key stretch. Obtain authPW and unwrapBKey



commit aeade122a6f506ca06a66a8c812c0a9bd531adaa
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Thu May 26 18:15:43 2016 +0300

    Implement key stretch. Obtain authPW and unwrapBKey

 configure.ac                 |    2 +
 src/ephy-sync-service.c      |  151 ++++++++++++++++++++++++++++++++++++++++--
 src/ephy-sync-service.h      |   14 +++-
 src/ephy-sync-window.c       |   43 +++++++++---
 src/resources/sync-dialog.ui |    4 +-
 5 files changed, 193 insertions(+), 21 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index af0d4ff..070c760 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,7 @@ GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=0.0.1
 LIBNOTIFY_REQUIRED=0.5.1
 GCR_REQUIRED=3.5.5
 AVAHI_REQUIRED=0.6.22
+NETTLE_REQUIRED=3.2
 
 # Tests
 
@@ -113,6 +114,7 @@ PKG_CHECK_MODULES([DEPENDENCIES], [
                  gcr-3 >= $GCR_REQUIRED
                  avahi-gobject >= $AVAHI_REQUIRED
                  avahi-client >= $AVAHI_REQUIRED
+                 nettle >= NETTLE_REQUIRED
                  ])
 
 PKG_CHECK_MODULES([WEB_EXTENSION], [
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index 0fda189..54afaea 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -1,6 +1,9 @@
 #include "ephy-sync-service.h"
 
-#include <stdio.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <nettle/hmac.h>
+#include <nettle/pbkdf2.h>
 
 struct _EphySyncService {
   GObject parent_instance;
@@ -8,13 +11,99 @@ struct _EphySyncService {
 
 G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
 
+static gchar *
+KW (const gchar *name)
+{
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  return g_strconcat ("identity.mozilla.com/picl/v1/",
+                      name,
+                      NULL);
+}
+
+static gchar *
+KWE (const gchar *name, const gchar *emailUTF8)
+{
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  return g_strconcat ("identity.mozilla.com/picl/v1/",
+                      name,
+                      ":",
+                      emailUTF8,
+                      NULL);
+}
+
+/*
+ * Runs 1000 PBKDF2 iterations using sha256 as hash function.
+ */
+static void pbkdf2_1k (gsize key_length, guint8 *key,
+                       gsize salt_length, guint8 *salt,
+                       gsize out_length, guint8 *out)
+{
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  pbkdf2_hmac_sha256 (key_length, key, 1000, salt_length, salt, out_length, out);
+}
+
+/*
+ * HMAC-based Extract-and-Expand Key Derivation Function.
+ * Uses sha256 as hash function.
+ * https://tools.ietf.org/html/rfc5869
+ */
+static void hkdf (gsize in_length, guint8 *in,
+                  gsize salt_length, guint8 *salt,
+                  gsize info_length, guint8 *info,
+                  gsize out_length, guint8 *out)
+{
+  struct hmac_sha256_ctx ctx;
+  const gsize hash_length = 32;
+  gsize i, offset = 0;
+  guint8 *tmp, *prk;
+  guint8 counter;
+
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+
+  if (out_length > hash_length * 255)
+    return;
+
+  /* If salt value was not provided, use an array of hash_length zeros */
+  if (salt == NULL) {
+    salt = g_malloc0 (hash_length);
+    salt_length = hash_length;
+  }
+
+  tmp = g_malloc0 (hash_length + info_length + 1);
+  prk = g_malloc0 (hash_length);
+
+  /* Step 1: Extract */
+  hmac_sha256_set_key (&ctx, salt_length, salt);
+  hmac_sha256_update (&ctx, in_length, in);
+  hmac_sha256_digest (&ctx, hash_length, prk);
+
+  /* Step 2: Expand */
+  hmac_sha256_set_key (&ctx, hash_length, prk);
+
+  for (i = 0, counter = 1; i < out_length; i += hash_length, counter++) {
+    memcpy (tmp + offset, info, info_length);
+    tmp[offset + info_length] = counter;
+
+    hmac_sha256_update (&ctx, offset + info_length + 1, tmp);
+    hmac_sha256_digest (&ctx, hash_length, tmp);
+
+    offset = hash_length;
+
+    memcpy (out + i, tmp, hash_length);
+  }
+
+  g_free (salt);
+  g_free (tmp);
+  g_free (prk);
+}
+
 static void
 ephy_sync_service_class_init (EphySyncServiceClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   object_class = object_class; // suppress warnings
 
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
   // TODO: Set finalize, dispose, set/get property methods
 }
@@ -22,20 +111,70 @@ ephy_sync_service_class_init (EphySyncServiceClass *klass)
 static void
 ephy_sync_service_init (EphySyncService *self)
 {
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 }
 
 EphySyncService *
 ephy_sync_service_new (void)
 {
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
   return EPHY_SYNC_SERVICE (g_object_new (EPHY_TYPE_SYNC_SERVICE,
                                           NULL));
 }
 
 void
-ephy_sync_service_stretch (void)
+ephy_sync_service_stretch (EphySyncService *self,
+                           const gchar *emailUTF8,
+                           const gchar *passwordUTF8,
+                           guint8 *authPW,
+                           guint8 *unwrapBKey)
 {
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  gchar *salt_stretch;
+  gchar *info_auth;
+  gchar *info_unwrap;
+  guint8 *quickStretchedPW;
+
+  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+
+  salt_stretch = KWE ("quickStretch", emailUTF8);
+  quickStretchedPW = g_malloc0 (TOKEN_LENGTH);
+  pbkdf2_1k (strlen (passwordUTF8), (guint8 *) passwordUTF8,
+             strlen (salt_stretch), (guint8 *) salt_stretch,
+             TOKEN_LENGTH, quickStretchedPW);
+
+  ephy_sync_service_display_hex ("quickStretchedPW", TOKEN_LENGTH, quickStretchedPW);
+
+  info_auth = KW ("authPW");
+  hkdf (TOKEN_LENGTH, quickStretchedPW,
+        0, NULL,
+        strlen (info_auth), (guint8 *) info_auth,
+        TOKEN_LENGTH, authPW);
+
+  info_unwrap = KW ("unwrapBkey");
+  hkdf (TOKEN_LENGTH, quickStretchedPW,
+        0, NULL,
+        strlen (info_unwrap), (guint8 *) info_unwrap,
+        TOKEN_LENGTH, unwrapBKey);
+
+  g_free (salt_stretch);
+  g_free (info_unwrap);
+  g_free (info_auth);
+  g_free (quickStretchedPW);
+}
+
+void
+ephy_sync_service_display_hex (const gchar *name, gsize length, guint8 *data)
+{
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+
+  g_printf ("%s:\n", name);
+  for (gsize i = 0; i < length; i++) {
+    g_printf ("%02x", data[i]);
+    if ((i + 1) % 8 == 0)
+      g_printf ("\n");
+  }
+  g_printf ("\n");
 }
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index d685963..5fdb681 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -5,12 +5,20 @@
 
 G_BEGIN_DECLS
 
-#define EPHY_TYPE_SYNC_SERVICE (ephy_sync_service_get_type())
+#define EPHY_TYPE_SYNC_SERVICE  (ephy_sync_service_get_type ())
+#define TOKEN_LENGTH            32
 
 G_DECLARE_FINAL_TYPE (EphySyncService, ephy_sync_service, EPHY, SYNC_SERVICE, GObject)
 
-EphySyncService        *ephy_sync_service_new           (void);
-void                    ephy_sync_service_stretch       (void);
+EphySyncService *ephy_sync_service_new          (void);
+void             ephy_sync_service_stretch      (EphySyncService *self,
+                                                 const gchar *emailUTF8,
+                                                 const gchar *passwordUTF8,
+                                                 guint8 *authPW,
+                                                 guint8 *unwrapBKey);
+void             ephy_sync_service_display_hex  (const gchar *name,
+                                                 gsize length,
+                                                 guint8 *data);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-window.c b/src/ephy-sync-window.c
index 8d23b6e..b47981b 100644
--- a/src/ephy-sync-window.c
+++ b/src/ephy-sync-window.c
@@ -1,6 +1,8 @@
 #include "ephy-sync-window.h"
+#include "ephy-sync-service.h"
 #include "ephy-gui.h"
 
+#include <glib/gstdio.h>
 #include <gtk/gtk.h>
 
 struct _EphySyncWindow {
@@ -27,15 +29,36 @@ enum {
 static GParamSpec *obj_properties[PROP_LAST];
 
 static void
-quickstretch (GSimpleAction *action,
-              GVariant      *parameter,
-              gpointer       user_data)
+submit_action (GSimpleAction *action,
+               GVariant      *parameter,
+               gpointer       user_data)
 {
+  const gchar *emailUTF8;
+  const gchar *passwordUTF8;
+  guint8 *authPW;
+  guint8 *unwrapBKey;
   EphySyncWindow *self = EPHY_SYNC_WINDOW (user_data);
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
-  printf("email:%s\n", gtk_entry_get_text (GTK_ENTRY (self->entry_email)));
-  printf("password:%s\n", gtk_entry_get_text (GTK_ENTRY (self->entry_password)));
+  emailUTF8 = gtk_entry_get_text (GTK_ENTRY (self->entry_email));
+  passwordUTF8 = gtk_entry_get_text (GTK_ENTRY (self->entry_password));
+  g_printf ("email: %s\n", emailUTF8);
+  g_printf ("password: %s\n", passwordUTF8);
+
+  authPW = g_malloc0 (TOKEN_LENGTH);
+  unwrapBKey = g_malloc0 (TOKEN_LENGTH);
+
+  ephy_sync_service_stretch (self->sync_service,
+                             emailUTF8,
+                             passwordUTF8,
+                             authPW,
+                             unwrapBKey);
+
+  ephy_sync_service_display_hex ("authPW", TOKEN_LENGTH, authPW);
+  ephy_sync_service_display_hex ("unwrapBKey", TOKEN_LENGTH, unwrapBKey);
+
+  g_free (authPW);
+  g_free (unwrapBKey);
 }
 
 static void
@@ -98,7 +121,7 @@ create_action_group (EphySyncWindow *self)
   GSimpleActionGroup *group;
 
   const GActionEntry entries[] = {
-    { "quickstretch", quickstretch }
+    { "submit_action", submit_action }
   };
 
   group = g_simple_action_group_new ();
@@ -113,7 +136,7 @@ ephy_sync_window_class_init (EphySyncWindowClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
   object_class->set_property = ephy_sync_window_set_property;
   object_class->get_property = ephy_sync_window_get_property;
@@ -139,7 +162,7 @@ ephy_sync_window_class_init (EphySyncWindowClass *klass)
 static void
 ephy_sync_window_init (EphySyncWindow *self)
 {
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
   gtk_widget_init_template (GTK_WIDGET (self));
 
@@ -156,7 +179,7 @@ ephy_sync_window_new (EphySyncService *sync_service)
 {
   EphySyncWindow *self;
 
-  printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
+  g_printf ("[%s:%d, %s]\n", __FILE__, __LINE__, __func__);
 
   self = g_object_new (EPHY_TYPE_SYNC_WINDOW,
                        "use-header-bar", TRUE,
diff --git a/src/resources/sync-dialog.ui b/src/resources/sync-dialog.ui
index 2e95416..df88b37 100644
--- a/src/resources/sync-dialog.ui
+++ b/src/resources/sync-dialog.ui
@@ -88,12 +88,12 @@
             </child>
             <child>
               <object class="GtkButton" id="btn_submit">
-                <property name="label" translatable="yes">_Stretch</property>
+                <property name="label" translatable="yes">_Submit</property>
                 <property name="visible">True</property>
                 <property name="use-underline">True</property>
                 <property name="sensitive">True</property>
                 <property name="valign">center</property>
-                <property name="action-name">sync.quickstretch</property>
+                <property name="action-name">sync.submit_action</property>
                 <style>
                   <class name="suggested-action"/>
                   <class name="text-button"/>


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