[epiphany/wip/ephy-sync] Add bookmark to BSO function



commit a41a455d9e476d5b0ec8d3b65c49b762207b2b06
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Sat Jul 30 13:56:13 2016 +0300

    Add bookmark to BSO function

 src/ephy-bookmark.c    |   37 +++++++++
 src/ephy-bookmark.h    |    1 +
 src/ephy-sync-crypto.c |  193 ++++++++++++++++++++++++++++++------------------
 src/ephy-sync-crypto.h |   24 +++++--
 4 files changed, 177 insertions(+), 78 deletions(-)
---
diff --git a/src/ephy-bookmark.c b/src/ephy-bookmark.c
index a877a82..9fdb178 100644
--- a/src/ephy-bookmark.c
+++ b/src/ephy-bookmark.c
@@ -19,7 +19,12 @@
 
 #include "ephy-bookmark.h"
 
+#include "ephy-shell.h"
+#include "ephy-sync-crypto.h"
+#include "ephy-sync-utils.h"
+
 #include <json-glib/json-glib.h>
+#include <string.h>
 
 struct _EphyBookmark {
   GObject      parent_instance;
@@ -27,6 +32,8 @@ struct _EphyBookmark {
   char        *url;
   char        *title;
   GSequence   *tags;
+
+  char        *id;
 };
 
 static JsonSerializableIface *serializable_iface = NULL;
@@ -141,6 +148,7 @@ ephy_bookmark_class_init (EphyBookmarkClass *klass)
 static void
 ephy_bookmark_init (EphyBookmark *self)
 {
+  self->id = ephy_sync_crypto_generate_random_string (12);
 }
 
 static JsonNode *
@@ -257,3 +265,32 @@ ephy_bookmark_get_tags (EphyBookmark *self)
 
   return self->tags;
 }
+
+char *
+ephy_bookmark_to_bso (EphyBookmark *self)
+{
+  EphySyncService *service;
+  guint8 *encrypted;
+  guint8 *sync_key;
+  char *serialized;
+  char *payload;
+  char *bso;
+  gsize length;
+
+  g_return_val_if_fail (EPHY_IS_BOOKMARK (self), NULL);
+
+  service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
+  sync_key = ephy_sync_crypto_decode_hex (ephy_sync_service_get_token (service, TOKEN_KB));
+  serialized = json_gobject_to_data (G_OBJECT (self), &length);
+  encrypted = ephy_sync_crypto_aes_256 (AES_256_MODE_ENCRYPT, sync_key,
+                                        (guint8 *)serialized, strlen (serialized), &length);
+  payload = ephy_sync_crypto_base64_urlsafe_encode (encrypted, length, FALSE);
+  bso = ephy_sync_utils_create_bso_json (self->id, payload);
+
+  g_free (sync_key);
+  g_free (serialized);
+  g_free (encrypted);
+  g_free (payload);
+
+  return bso;
+}
diff --git a/src/ephy-bookmark.h b/src/ephy-bookmark.h
index e752f58..c6142f0 100644
--- a/src/ephy-bookmark.h
+++ b/src/ephy-bookmark.h
@@ -38,6 +38,7 @@ void                 ephy_bookmark_remove_tag   (EphyBookmark *self,
 void                 ephy_bookmark_set_tags     (EphyBookmark *self,
                                                  GSequence    *tags);
 GSequence           *ephy_bookmark_get_tags     (EphyBookmark *self);
+char                *ephy_bookmark_to_bso       (EphyBookmark *self);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-crypto.c b/src/ephy-sync-crypto.c
index 1e6f213..a194360 100644
--- a/src/ephy-sync-crypto.c
+++ b/src/ephy-sync-crypto.c
@@ -264,37 +264,6 @@ kw (const gchar *name)
   return g_strconcat ("identity.mozilla.com/picl/v1/", name, NULL);
 }
 
-static gchar *
-base64_urlsafe_strip (guint8 *data,
-                      gsize   data_length)
-{
-  gchar *encoded;
-  gchar *base64;
-  gsize start;
-  gssize end;
-
-  base64 = g_base64_encode (data, data_length);
-
-  start = 0;
-  while (start < strlen (base64) && base64[start] == '=')
-    start++;
-
-  end = strlen (base64) - 1;
-  while (end >= 0 && base64[end] == '=')
-    end--;
-
-  encoded = g_strndup (base64 + start, end - start + 1);
-
-  /* Replace '+' with '-' */
-  g_strcanon (encoded, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/", '-');
-  /* Replace '/' with '_' */
-  g_strcanon (encoded, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-", '_');
-
-  g_free (base64);
-
-  return encoded;
-}
-
 static guint8 *
 xor (guint8 *a,
      guint8 *b,
@@ -328,26 +297,6 @@ are_equal (guint8 *a,
 }
 
 static gchar *
-generate_random_string (gsize length)
-{
-  guchar *bytes;
-  gchar *base64_string;
-  gchar *string;
-
-  bytes = g_malloc (length);
-  for (gsize i = 0; i < length; i++)
-    bytes[i] = g_random_int ();
-
-  base64_string = g_base64_encode (bytes, length);
-  string = g_strndup (base64_string, length);
-
-  g_free (bytes);
-  g_free (base64_string);
-
-  return string;
-}
-
-static gchar *
 find_and_replace_string (const gchar *src,
                          const gchar *find,
                          const gchar *repl)
@@ -636,6 +585,22 @@ random_func (void   *ctx,
     dst[i] = g_random_int ();
 }
 
+static void
+base64_to_base64_urlsafe (gchar *text)
+{
+  /* Replace '+' with '-' and '/' with '_' */
+  g_strcanon (text, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=/", '-');
+  g_strcanon (text, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=-", '_');
+}
+
+static void
+base64_urlsafe_to_base64 (gchar *text)
+{
+  /* Replace '-' with '+' and '_' with '/' */
+  g_strcanon (text, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=_", '+');
+  g_strcanon (text, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=+", '/');
+}
+
 EphySyncCryptoProcessedKFT *
 ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken)
 {
@@ -820,7 +785,7 @@ ephy_sync_crypto_compute_hawk_header (const gchar               *url,
   }
 
   nonce = has_options ? options->nonce : NULL;
-  nonce = nonce ? nonce : generate_random_string (6);
+  nonce = nonce ? nonce : ephy_sync_crypto_generate_random_string (6);
   hash = has_options ? options->hash : NULL;
   payload = has_options ? options->payload : NULL;
 
@@ -934,8 +899,8 @@ ephy_sync_crypto_create_assertion (const gchar              *certificate,
 
   expires_at = g_get_real_time () / 1000 + duration * 1000;
   body = g_strdup_printf ("{\"exp\": %lu, \"aud\": \"%s\"}", expires_at, audience);
-  body_b64 = base64_urlsafe_strip ((guint8 *) body, strlen (body));
-  header_b64 = base64_urlsafe_strip ((guint8 *) header, strlen (header));
+  body_b64 = ephy_sync_crypto_base64_urlsafe_encode ((guint8 *) body, strlen (body), TRUE);
+  header_b64 = ephy_sync_crypto_base64_urlsafe_encode ((guint8 *) header, strlen (header), TRUE);
   to_sign = g_strdup_printf ("%s.%s", header_b64, body_b64);
 
   mpz_init (signature);
@@ -958,7 +923,7 @@ ephy_sync_crypto_create_assertion (const gchar              *certificate,
     goto out;
   }
 
-  sig_b64 = base64_urlsafe_strip (sig, count);
+  sig_b64 = ephy_sync_crypto_base64_urlsafe_encode (sig, count, TRUE);
   assertion = g_strdup_printf ("%s~%s.%s.%s",
                                certificate, header_b64, body_b64, sig_b64);
 
@@ -976,36 +941,120 @@ out:
   return assertion;
 }
 
+gchar *
+ephy_sync_crypto_generate_random_string (gsize length)
+{
+  guchar *bytes;
+  gchar *base64_string;
+  gchar *string;
+
+  bytes = g_malloc (length);
+  for (gsize i = 0; i < length; i++)
+    bytes[i] = g_random_int ();
+
+  base64_string = g_base64_encode (bytes, length);
+  base64_to_base64_urlsafe (base64_string);
+  string = g_strndup (base64_string, length);
+
+  g_free (bytes);
+  g_free (base64_string);
+
+  return string;
+}
+
+gchar *
+ephy_sync_crypto_base64_urlsafe_encode (guint8   *data,
+                                        gsize     data_length,
+                                        gboolean  strip)
+{
+  gchar *encoded;
+  gchar *base64;
+  gsize start;
+  gssize end;
+
+  base64 = g_base64_encode (data, data_length);
+
+  if (strip == FALSE) {
+    base64_to_base64_urlsafe (base64);
+    return base64;
+  }
+
+  /* Strip all the '=' */
+  start = 0;
+  while (start < strlen (base64) && base64[start] == '=')
+    start++;
+
+  end = strlen (base64) - 1;
+  while (end >= 0 && base64[end] == '=')
+    end--;
+
+  encoded = g_strndup (base64 + start, end - start + 1);
+  base64_to_base64_urlsafe (encoded);
+
+  g_free (base64);
+
+  return encoded;
+}
+
 guint8 *
-ephy_sync_crypto_encode_aes_256 (const guint8 *key,
-                                 const guint8 *data,
-                                 gsize         data_length)
+ephy_sync_crypto_base64_urlsafe_decode (gchar *text,
+                                        gsize *out_length)
 {
-  struct aes256_ctx aes;
-  guint8 *out;
+  guint8 *decoded;
+  gchar *text_copy;
 
-  g_assert (data_length % AES_BLOCK_SIZE == 0);
+  text_copy = g_strdup (text);
+  base64_urlsafe_to_base64 (text_copy);
+  decoded = g_base64_decode (text_copy, out_length);
 
-  out = g_malloc (data_length);
-  aes256_set_encrypt_key (&aes, key);
-  aes256_encrypt (&aes, data_length, out, data);
+  g_free (text_copy);
 
-  return out;
+  return decoded;
 }
 
 guint8 *
-ephy_sync_crypto_decode_aes_256 (const guint8 *key,
-                                 const guint8 *data,
-                                 gsize         data_length)
+ephy_sync_crypto_aes_256 (EphySyncCryptoAES256Mode  mode,
+                          const guint8             *key,
+                          const guint8             *data,
+                          gsize                     data_length,
+                          gsize                    *out_length)
 {
   struct aes256_ctx aes;
+  gsize padded_length;
+  guint8 *padded_data;
   guint8 *out;
 
-  g_assert (data_length % AES_BLOCK_SIZE == 0);
+  g_return_val_if_fail (key != NULL, NULL);
+  g_return_val_if_fail (data != NULL, NULL);
+
+  if (mode == AES_256_MODE_DECRYPT)
+    g_assert (data_length % AES_BLOCK_SIZE == 0);
+
+  padded_length = data_length;
+  if (data_length % AES_BLOCK_SIZE != 0)
+    padded_length = data_length + (AES_BLOCK_SIZE - data_length % AES_BLOCK_SIZE);
+
+  out = g_malloc (padded_length);
+  padded_data = g_malloc0 (padded_length);
+  memcpy (padded_data, data, data_length);
+
+  switch (mode) {
+    case AES_256_MODE_ENCRYPT:
+      aes256_set_encrypt_key (&aes, key);
+      aes256_encrypt (&aes, padded_length, out, padded_data);
+      break;
+    case AES_256_MODE_DECRYPT:
+      aes256_set_decrypt_key (&aes, key);
+      aes256_decrypt (&aes, padded_length, out, padded_data);
+      break;
+    default:
+      g_assert_not_reached ();
+  }
+
+  if (out_length != NULL)
+    *out_length = padded_length;
 
-  out = g_malloc (data_length);
-  aes256_set_decrypt_key (&aes, key);
-  aes256_decrypt (&aes, data_length, out, data);
+  g_free (padded_data);
 
   return out;
 }
diff --git a/src/ephy-sync-crypto.h b/src/ephy-sync-crypto.h
index 902f285..4cf1adb 100644
--- a/src/ephy-sync-crypto.h
+++ b/src/ephy-sync-crypto.h
@@ -26,6 +26,11 @@ G_BEGIN_DECLS
 
 #define EPHY_SYNC_TOKEN_LENGTH 32
 
+typedef enum {
+  AES_256_MODE_ENCRYPT,
+  AES_256_MODE_DECRYPT
+} EphySyncCryptoAES256Mode;
+
 typedef struct {
   gchar *app;
   gchar *dlg;
@@ -125,13 +130,20 @@ gchar                      *ephy_sync_crypto_create_assertion        (const gcha
                                                                       guint64                   duration,
                                                                       EphySyncCryptoRSAKeyPair *keypair);
 
-guint8                     *ephy_sync_crypto_encode_aes_256          (const guint8 *key,
-                                                                      const guint8 *data,
-                                                                      gsize         data_length);
+gchar                      *ephy_sync_crypto_generate_random_string  (gsize length);
+
+gchar                      *ephy_sync_crypto_base64_urlsafe_encode   (guint8   *data,
+                                                                      gsize     data_length,
+                                                                      gboolean  strip);
+
+guint8                     *ephy_sync_crypto_base64_urlsafe_decode   (gchar *text,
+                                                                      gsize *out_length);
 
-guint8                     *ephy_sync_crypto_decode_aes_256          (const guint8 *key,
-                                                                      const guint8 *data,
-                                                                      gsize         data_length);
+guint8                     *ephy_sync_crypto_aes_256                 (EphySyncCryptoAES256Mode  mode,
+                                                                      const guint8             *key,
+                                                                      const guint8             *data,
+                                                                      gsize                     data_length,
+                                                                      gsize                    *out_length);
 
 gchar                      *ephy_sync_crypto_encode_hex              (guint8 *data,
                                                                       gsize   data_length);


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