gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: -first cut at contract encryptio


From: gnunet
Subject: [taler-exchange] branch master updated: -first cut at contract encryption and decryption
Date: Mon, 28 Mar 2022 13:57:51 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new a227ee6d -first cut at contract encryption and decryption
a227ee6d is described below

commit a227ee6d1bd979ae87ab9afda27f180c840313bf
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Mon Mar 28 13:57:43 2022 +0200

    -first cut at contract encryption and decryption
---
 src/include/taler_exchange_service.h             |   4 +
 src/lib/exchange_api_purse_create_with_deposit.c |  25 +-
 src/util/Makefile.am                             |   3 +
 src/util/crypto_contract.c                       | 300 ++++++++++++++++++++++-
 4 files changed, 319 insertions(+), 13 deletions(-)

diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index cf462425..00c8c101 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -4287,6 +4287,9 @@ struct TALER_EXCHANGE_PurseDeposit
  * @param purse_expiration when will the unmerged purse expire
  * @param num_deposits length of the @a deposits array
  * @param deposits array of deposits to make into the purse
+ * @param upload_contract true to upload the contract; must
+ *        be FALSE for repeated calls to this API for the
+ *        same purse (i.e. when adding more deposits).
  * @param cb function to call with the exchange's result
  * @param cb_cls closure for @a cb
  * @return the request handle; NULL upon error
@@ -4301,6 +4304,7 @@ TALER_EXCHANGE_purse_create_with_deposit (
   struct GNUNET_TIME_Timestamp purse_expiration,
   unsigned int num_deposits,
   const struct TALER_EXCHANGE_PurseDeposit *deposits,
+  bool upload_contract,
   TALER_EXCHANGE_PurseCreateDepositCallback cb,
   void *cb_cls);
 
diff --git a/src/lib/exchange_api_purse_create_with_deposit.c 
b/src/lib/exchange_api_purse_create_with_deposit.c
index 6765b777..e39cb076 100644
--- a/src/lib/exchange_api_purse_create_with_deposit.c
+++ b/src/lib/exchange_api_purse_create_with_deposit.c
@@ -202,6 +202,7 @@ TALER_EXCHANGE_purse_create_with_deposit (
   struct GNUNET_TIME_Timestamp purse_expiration,
   unsigned int num_deposits,
   const struct TALER_EXCHANGE_PurseDeposit *deposits,
+  bool upload_contract,
   TALER_EXCHANGE_PurseCreateDepositCallback cb,
   void *cb_cls)
 {
@@ -335,23 +336,25 @@ TALER_EXCHANGE_purse_create_with_deposit (
   }
   GNUNET_free (url);
   {
-    void *econtract;
-    size_t econtract_size;
+    void *econtract = NULL;
+    size_t econtract_size = 0;
 
-    TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
-                                             contract_priv,
-                                             merge_priv,
-                                             contract_terms,
-                                             &econtract,
-                                             &econtract_size);
+    if (upload_contract)
+      TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
+                                               contract_priv,
+                                               merge_priv,
+                                               contract_terms,
+                                               &econtract,
+                                               &econtract_size);
     create_obj = GNUNET_JSON_PACK (
       TALER_JSON_pack_amount ("amount",
                               &purse_value_after_fees),
       GNUNET_JSON_pack_uint64 ("min_age",
                                min_age),
-      GNUNET_JSON_pack_data_varsize ("econtract",
-                                     econtract,
-                                     econtract_size),
+      GNUNET_JSON_pack_allow_null (
+        GNUNET_JSON_pack_data_varsize ("econtract",
+                                       econtract,
+                                       econtract_size)),
       GNUNET_JSON_pack_data_auto ("contract_pub",
                                   &contract_pub),
       GNUNET_JSON_pack_data_auto ("merge_pub",
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 8ef9e146..b92c427b 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -105,8 +105,11 @@ libtalerutil_la_SOURCES = \
 
 libtalerutil_la_LIBADD = \
   -lgnunetutil \
+  -lsodium \
+  -ljansson \
   $(LIBGCRYPT_LIBS) \
   -lmicrohttpd $(XLIB) \
+  -lz \
   -lm
 
 libtalerutil_la_LDFLAGS = \
diff --git a/src/util/crypto_contract.c b/src/util/crypto_contract.c
index 7f684d80..5117712e 100644
--- a/src/util/crypto_contract.c
+++ b/src/util/crypto_contract.c
@@ -20,6 +20,191 @@
  */
 #include "platform.h"
 #include "taler_util.h"
+#include <zlib.h>
+#include "taler_exchange_service.h"
+
+
+/**
+ * Nonce used for encryption, 24 bytes.
+ */
+struct NonceP
+{
+  uint8_t nonce[crypto_secretbox_NONCEBYTES];
+};
+
+/**
+ * Specifies a key used for symmetric encryption, 32 bytes.
+ */
+struct SymKeyP
+{
+  uint32_t key[8];
+};
+
+
+/**
+ * Compute @a key.
+ *
+ * @param key_material key for calculation
+ * @param key_m_len length of key
+ * @param nonce nonce for calculation
+ * @param salt salt value for calculation
+ * @param[out] key where to write the en-/description key
+ */
+static void
+derive_key (const void *key_material,
+            size_t key_m_len,
+            const struct NonceP *nonce,
+            const char *salt,
+            struct SymKeyP *key)
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_kdf (key,
+                                    sizeof (*key),
+                                    /* salt / XTS */
+                                    nonce,
+                                    sizeof (*nonce),
+                                    /* ikm */
+                                    key_material,
+                                    key_m_len,
+                                    /* info chunks */
+                                    /* The "salt" passed here is actually not 
something random,
+                                       but a protocol-specific identifier 
string.  Thus
+                                       we pass it as a context info to the 
HKDF */
+                                    salt,
+                                    strlen (salt),
+                                    NULL,
+                                    0));
+}
+
+
+/**
+ * Encryption of data.
+ *
+ * @param nonce value to use for the nonce
+ * @param key key which is used to derive a key/iv pair from
+ * @param key_len length of key
+ * @param data data to encrypt
+ * @param data_size size of the data
+ * @param salt salt value which is used for key derivation
+ * @param[out] res ciphertext output
+ * @param[out] res_size size of the ciphertext
+ */
+static void
+encrypt (const struct NonceP *nonce,
+         const void *key,
+         size_t key_len,
+         const void *data,
+         size_t data_size,
+         const char *salt,
+         void **res,
+         size_t *res_size)
+{
+  size_t ciphertext_size;
+  struct SymKeyP skey;
+
+  derive_key (key,
+              key_len,
+              nonce,
+              salt,
+              &skey);
+  ciphertext_size = crypto_secretbox_NONCEBYTES
+                    + crypto_secretbox_MACBYTES + data_size;
+  *res_size = ciphertext_size;
+  *res = GNUNET_malloc (ciphertext_size);
+  memcpy (*res, nonce, crypto_secretbox_NONCEBYTES);
+  GNUNET_assert (0 ==
+                 crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
+                                        data,
+                                        data_size,
+                                        (void *) nonce,
+                                        (void *) &skey));
+}
+
+
+/**
+ * Decryption of data like encrypted recovery document etc.
+ *
+ * @param key key which is used to derive a key/iv pair from
+ * @param key_len length of key
+ * @param data data to decrypt
+ * @param data_size size of the data
+ * @param salt salt value which is used for key derivation
+ * @param[out] res plaintext output
+ * @param[out] res_size size of the plaintext
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+decrypt (const void *key,
+         size_t key_len,
+         const void *data,
+         size_t data_size,
+         const char *salt,
+         void **res,
+         size_t *res_size)
+{
+  const struct NonceP *nonce;
+  struct SymKeyP skey;
+  size_t plaintext_size;
+
+  if (data_size < crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  nonce = data;
+  derive_key (key,
+              key_len,
+              nonce,
+              salt,
+              &skey);
+  plaintext_size = data_size - (crypto_secretbox_NONCEBYTES
+                                + crypto_secretbox_MACBYTES);
+  *res = GNUNET_malloc (plaintext_size);
+  *res_size = plaintext_size;
+  if (0 != crypto_secretbox_open_easy (*res,
+                                       data + crypto_secretbox_NONCEBYTES,
+                                       data_size - crypto_secretbox_NONCEBYTES,
+                                       (void *) nonce,
+                                       (void *) &skey))
+  {
+    GNUNET_break (0);
+    GNUNET_free (*res);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Header for encrypted contracts.
+ */
+struct ContractHeader
+{
+  /**
+   * Type of the contract, in NBO.
+   */
+  uint32_t ctype;
+
+  /**
+   * Length of the encrypted contract, in NBO.
+   */
+  uint32_t clen;
+
+  /**
+   * Included key material, depending on @e ctype.
+   */
+  union
+  {
+    struct TALER_PurseMergePrivateKeyP merge_priv;
+  } keys;
+
+};
+
+
+/**
+ * Salt we use when encrypting contracts for merge.
+ */
+#define MERGE_SALT "p2p-merge-contract"
 
 
 void
@@ -29,9 +214,52 @@ TALER_CRYPTO_contract_encrypt_for_merge (
   const struct TALER_PurseMergePrivateKeyP *merge_priv,
   const json_t *contract_terms,
   void **econtract,
-
   size_t *econtract_size)
 {
+  struct GNUNET_HashCode key;
+  char *cstr;
+  size_t clen;
+  void *xbuf;
+  struct ContractHeader *hdr;
+  struct NonceP nonce;
+  uLongf cbuf_size;
+  int ret;
+
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
+                                           &purse_pub->eddsa_pub,
+                                           &key));
+  cstr = json_dumps (contract_terms,
+                     JSON_COMPACT | JSON_SORT_KEYS);
+  clen = strlen (cstr);
+  cbuf_size = compressBound (clen);
+  xbuf = GNUNET_malloc (cbuf_size);
+  ret = compress (xbuf,
+                  &cbuf_size,
+                  (const Bytef *) cstr,
+                  clen);
+  GNUNET_assert (Z_OK == ret);
+  free (cstr);
+  hdr = GNUNET_malloc (sizeof (*hdr) + cbuf_size);
+  hdr->ctype = htonl (TALER_EXCHANGE_CONTRACT_PAYMENT_OFFER);
+  hdr->clen = htonl ((uint32_t) clen);
+  hdr->keys.merge_priv = *merge_priv;
+  memcpy (&hdr[1],
+          xbuf,
+          cbuf_size);
+  GNUNET_free (xbuf);
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              &nonce,
+                              sizeof (nonce));
+  encrypt (&nonce,
+           &key,
+           sizeof (key),
+           hdr,
+           sizeof (*hdr) + cbuf_size,
+           MERGE_SALT,
+           econtract,
+           econtract_size);
+  GNUNET_free (hdr);
 }
 
 
@@ -43,5 +271,73 @@ TALER_CRYPTO_contract_decrypt_for_merge (
   size_t econtract_size,
   struct TALER_PurseMergePrivateKeyP *merge_priv)
 {
-  return NULL;
+  struct GNUNET_HashCode key;
+  void *xhdr;
+  size_t hdr_size;
+  const struct ContractHeader *hdr;
+  char *cstr;
+  uLongf clen;
+  json_error_t json_error;
+  json_t *ret;
+
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
+                                &purse_pub->eddsa_pub,
+                                &key))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  if (GNUNET_OK !=
+      decrypt (&key,
+               sizeof (key),
+               econtract,
+               econtract_size,
+               MERGE_SALT,
+               &xhdr,
+               &hdr_size))
+  {
+    GNUNET_break_op (0);
+    return NULL;
+  }
+  if (hdr_size < sizeof (*hdr))
+  {
+    GNUNET_break_op (0);
+    GNUNET_free (xhdr);
+    return NULL;
+  }
+  hdr = xhdr;
+  clen = ntohl (hdr->clen);
+  if (clen >= GNUNET_MAX_MALLOC_CHECKED)
+  {
+    GNUNET_break_op (0);
+    GNUNET_free (xhdr);
+    return NULL;
+  }
+  cstr = GNUNET_malloc (clen + 1);
+  if (Z_OK !=
+      uncompress ((Bytef *) cstr,
+                  &clen,
+                  (const Bytef *) &hdr[1],
+                  hdr_size - sizeof (*hdr)))
+  {
+    GNUNET_break_op (0);
+    GNUNET_free (cstr);
+    GNUNET_free (xhdr);
+    return NULL;
+  }
+  *merge_priv = hdr->keys.merge_priv;
+  GNUNET_free (xhdr);
+  ret = json_loadb ((char *) cstr,
+                    clen,
+                    JSON_DECODE_ANY,
+                    &json_error);
+  if (NULL == ret)
+  {
+    GNUNET_break_op (0);
+    GNUNET_free (cstr);
+    return NULL;
+  }
+  GNUNET_free (cstr);
+  return ret;
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]