]> source.dussan.org Git - rspamd.git/commitdiff
Add more methods to keypair management
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 6 Feb 2016 01:29:49 +0000 (01:29 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 6 Feb 2016 01:29:49 +0000 (01:29 +0000)
src/libcryptobox/keypair.c
src/libcryptobox/keypair.h

index 0cd6f9eb38d21d8a026ef0506ab28ba7f22faac5..c56daafa90101990478c61cbffbef97ca2117568 100644 (file)
@@ -395,6 +395,38 @@ rspamd_pubkey_from_hex (const gchar *hex,
        return pk;
 }
 
+struct rspamd_cryptobox_pubkey*
+rspamd_pubkey_from_bin (const guchar *raw,
+               gsize len,
+               enum rspamd_cryptobox_keypair_type type,
+               enum rspamd_cryptobox_mode alg)
+{
+       gsize expected_len;
+       guint pklen;
+       struct rspamd_cryptobox_pubkey *pk;
+       guchar *pk_data;
+
+       g_assert (raw != NULL && len > 0);
+
+       expected_len = (type == RSPAMD_KEYPAIR_KEX) ?
+                       rspamd_cryptobox_pk_bytes (alg) : rspamd_cryptobox_pk_sig_bytes (alg);
+
+       if (len != expected_len) {
+               return NULL;
+       }
+
+       pk = rspamd_cryptobox_pubkey_alloc (type, alg);
+       pk_data = rspamd_cryptobox_pubkey_pk (pk, &pklen);
+
+       memcpy (raw, pk_data, pklen);
+       rspamd_cryptobox_hash (pk->id, pk_data, pklen, NULL, 0);
+       pk->alg = alg;
+       pk->type = type;
+
+       return pk;
+}
+
+
 const guchar *
 rspamd_pubkey_get_nm (struct rspamd_cryptobox_pubkey *p)
 {
@@ -557,3 +589,173 @@ rspamd_keypair_component (struct rspamd_cryptobox_keypair *kp,
 
        return ret;
 }
+
+struct rspamd_cryptobox_keypair *
+rspamd_keypair_from_ucl (const ucl_object_t *obj)
+{
+       const ucl_object_t *privkey, *pubkey, *elt;
+       const gchar *str;
+       enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
+       enum rspamd_cryptobox_mode mode = RSPAMD_CRYPTOBOX_MODE_25519;
+       gboolean is_hex = FALSE;
+       struct rspamd_cryptobox_keypair *kp;
+       guint len;
+       gsize ucl_len;
+       gint dec_len;
+       gpointer target;
+
+       if (ucl_object_type (obj) != UCL_OBJECT) {
+               return NULL;
+       }
+
+       pubkey = ucl_object_find_any_key (obj, "pubkey", "public", "public_key",
+                       NULL);
+       if (pubkey == NULL || ucl_object_type (pubkey) != UCL_STRING) {
+               return NULL;
+       }
+
+       privkey = ucl_object_find_any_key (obj, "privkey", "private", "private_key",
+                       "secret", "secret_key", NULL);
+       if (privkey == NULL || ucl_object_type (privkey) != UCL_STRING) {
+               return NULL;
+       }
+
+       /* Optional fields */
+       elt = ucl_object_find_key (obj, "type");
+       if (elt && ucl_object_type (elt) == UCL_STRING) {
+               str = ucl_object_tostring (elt);
+
+               if (g_ascii_strcasecmp (str, "kex") == 0) {
+                       type = RSPAMD_KEYPAIR_KEX;
+               }
+               else if (g_ascii_strcasecmp (str, "sign") == 0) {
+                       type = RSPAMD_KEYPAIR_SIGN;
+               }
+               /* TODO: handle errors */
+       }
+
+       elt = ucl_object_find_key (obj, "algorithm");
+       if (elt && ucl_object_type (elt) == UCL_STRING) {
+               str = ucl_object_tostring (elt);
+
+               if (g_ascii_strcasecmp (str, "curve25519") == 0) {
+                       mode = RSPAMD_CRYPTOBOX_MODE_25519;
+               }
+               else if (g_ascii_strcasecmp (str, "nistp256") == 0) {
+                       mode = RSPAMD_CRYPTOBOX_MODE_NIST;
+               }
+               /* TODO: handle errors */
+       }
+
+       elt = ucl_object_find_key (obj, "encoding");
+       if (elt && ucl_object_type (elt) == UCL_STRING) {
+               str = ucl_object_tostring (elt);
+
+               if (g_ascii_strcasecmp (str, "hex") == 0) {
+                       is_hex = TRUE;
+               }
+               /* TODO: handle errors */
+       }
+
+       kp = rspamd_keypair_new (type, mode);
+       g_assert (kp != NULL);
+
+       target = rspamd_cryptobox_keypair_pk (kp, &len);
+       str = ucl_object_tolstring (pubkey, &ucl_len);
+
+       if (is_hex) {
+               dec_len = rspamd_decode_hex_buf (str, ucl_len, target, len);
+       }
+       else {
+               dec_len = rspamd_decode_base32_buf (str, ucl_len, target, len);
+       }
+
+       if (dec_len != (gint)len) {
+               rspamd_keypair_unref (kp);
+
+               return NULL;
+       }
+
+       target = rspamd_cryptobox_keypair_sk (kp, &len);
+       str = ucl_object_tolstring (privkey, &ucl_len);
+
+       if (is_hex) {
+               dec_len = rspamd_decode_hex_buf (str, ucl_len, target, len);
+       }
+       else {
+               dec_len = rspamd_decode_base32_buf (str, ucl_len, target, len);
+       }
+
+       if (dec_len != (gint)len) {
+               rspamd_keypair_unref (kp);
+
+               return NULL;
+       }
+
+       return kp;
+}
+
+ucl_object_t *
+rspamd_keypair_to_ucl (struct rspamd_cryptobox_keypair *kp,
+               gboolean is_hex)
+{
+       ucl_object_t *ucl_out, *elt;
+       gint how = 0;
+       GString *keypair_out;
+       const gchar *encoding;
+
+       g_assert (kp != NULL);
+
+       if (is_hex) {
+               how |= RSPAMD_KEYPAIR_HEX;
+               encoding = "hex";
+       }
+       else {
+               how |= RSPAMD_KEYPAIR_BASE32;
+               encoding = "base32";
+       }
+
+       ucl_out = ucl_object_typed_new (UCL_OBJECT);
+       elt = ucl_object_typed_new (UCL_OBJECT);
+       ucl_object_insert_key (ucl_out, elt, "keypair", 0, false);
+
+       /* pubkey part */
+       keypair_out = rspamd_keypair_print (kp,
+                       RSPAMD_KEYPAIR_PUBKEY|how);
+       ucl_object_insert_key (elt,
+                       ucl_object_fromlstring (keypair_out->str, keypair_out->len),
+                       "pubkey", 0, false);
+       g_string_free (keypair_out, TRUE);
+
+       /* privkey part */
+       keypair_out = rspamd_keypair_print (kp,
+                       RSPAMD_KEYPAIR_PRIVKEY|how);
+       ucl_object_insert_key (elt,
+                       ucl_object_fromlstring (keypair_out->str, keypair_out->len),
+                       "privkey", 0, false);
+       g_string_free (keypair_out, TRUE);
+
+       keypair_out = rspamd_keypair_print (kp,
+                       RSPAMD_KEYPAIR_ID|how);
+       ucl_object_insert_key (elt,
+                       ucl_object_fromlstring (keypair_out->str, keypair_out->len),
+                       "id", 0, false);
+
+       ucl_object_insert_key (elt,
+                       ucl_object_fromstring (encoding),
+                       "encoding", 0, false);
+
+       ucl_object_insert_key (elt,
+                       ucl_object_fromstring (
+                                       kp->alg == RSPAMD_CRYPTOBOX_MODE_NIST ?
+                                                       "nistp256" : "curve25519"),
+                                       "algorithm", 0, false);
+
+       ucl_object_insert_key (elt,
+                       ucl_object_fromstring (
+                                       kp->type == RSPAMD_KEYPAIR_KEX ?
+                                                       "kex" : "sign"),
+                                       "type", 0, false);
+
+       return ucl_out;
+}
index 613c1296d968c8a593f2a35788c2514b8fa1dc9d..697e06a3d83ad5bbef2163a8279324156673aa4f 100644 (file)
@@ -93,6 +93,18 @@ struct rspamd_cryptobox_pubkey* rspamd_pubkey_from_hex (const gchar *hex,
                enum rspamd_cryptobox_keypair_type type,
                enum rspamd_cryptobox_mode alg);
 
+/**
+ * Load pubkey from raw chunk string
+ * @param hex input data
+ * @param type type of key (signing or kex)
+ * @param alg algorithm of the key (nist or curve25519)
+ * @return new pubkey or NULL in case of error
+ */
+struct rspamd_cryptobox_pubkey* rspamd_pubkey_from_bin (const guchar *raw,
+               gsize len,
+               enum rspamd_cryptobox_keypair_type type,
+               enum rspamd_cryptobox_mode alg);
+
 
 /**
  * Decrease refcount for the specific pubkey (or destroy when refcount == 0)
@@ -195,4 +207,19 @@ GString *rspamd_keypair_print (struct rspamd_cryptobox_keypair *kp,
 const guchar * rspamd_keypair_component (struct rspamd_cryptobox_keypair *kp,
                guint ncomp, guint *len);
 
+/**
+ * Create a new keypair from ucl object
+ * @param obj object to load
+ * @return new structure or NULL if an object is invalid
+ */
+struct rspamd_cryptobox_keypair * rspamd_keypair_from_ucl (const ucl_object_t *obj);
+
+/**
+ * Converts keypair to ucl object
+ * @param kp
+ * @return
+ */
+ucl_object_t * rspamd_keypair_to_ucl (struct rspamd_cryptobox_keypair *kp,
+               gboolean is_hex);
+
 #endif /* SRC_LIBCRYPTOBOX_KEYPAIR_H_ */