aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-05-02 17:29:41 +0200
committerChristian Grothoff <christian@grothoff.org>2023-05-02 17:29:41 +0200
commitffd4057c61a1c507e348b76d1df10641c7ed64b1 (patch)
tree96754a5de2d3468f2ad361771d4127e9979b3f5c
parent41cb79c685b25bcf2c3e566f25c386c89442cbeb (diff)
use same canonicalization of JSON as for contract hashes when doing normal JSON hashing
-rw-r--r--src/json/json.c168
-rw-r--r--src/util/util.c169
2 files changed, 169 insertions, 168 deletions
diff --git a/src/json/json.c b/src/json/json.c
index 7d7e4ecba..832863f31 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -62,170 +62,6 @@ contains_real (const json_t *json)
/**
- * Dump character in the low range into @a buf
- * following RFC 8785.
- *
- * @param[in,out] buf buffer to modify
- * @param val value to dump
- */
-static void
-lowdump (struct GNUNET_Buffer *buf,
- unsigned char val)
-{
- char scratch[7];
-
- switch (val)
- {
- case 0x8:
- GNUNET_buffer_write (buf,
- "\\b",
- 2);
- break;
- case 0x9:
- GNUNET_buffer_write (buf,
- "\\t",
- 2);
- break;
- case 0xA:
- GNUNET_buffer_write (buf,
- "\\n",
- 2);
- break;
- case 0xC:
- GNUNET_buffer_write (buf,
- "\\f",
- 2);
- break;
- case 0xD:
- GNUNET_buffer_write (buf,
- "\\r",
- 2);
- break;
- default:
- GNUNET_snprintf (scratch,
- sizeof (scratch),
- "\\u%04x",
- (unsigned int) val);
- GNUNET_buffer_write (buf,
- scratch,
- 6);
- break;
- }
-}
-
-
-/**
- * Re-encode string at @a inp to match RFC 8785 (section 3.2.2.2).
- *
- * @param[in,out] inp pointer to string to re-encode
- * @return number of bytes in resulting @a inp
- */
-static size_t
-rfc8785encode (char **inp)
-{
- struct GNUNET_Buffer buf = { 0 };
- size_t left = strlen (*inp) + 1;
- size_t olen;
- char *in = *inp;
- const char *pos = in;
-
- GNUNET_buffer_prealloc (&buf,
- left + 40);
- buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
- while (1)
- {
- int mbl = u8_mblen ((unsigned char *) pos,
- left);
- unsigned char val;
-
- if (0 == mbl)
- break;
- val = (unsigned char) *pos;
- if ( (1 == mbl) &&
- (val <= 0x1F) )
- {
- /* Should not happen, as input is produced by
- * JSON stringification */
- GNUNET_break (0);
- lowdump (&buf,
- val);
- }
- else if ( (1 == mbl) && ('\\' == *pos) )
- {
- switch (*(pos + 1))
- {
- case '\\':
- mbl = 2;
- GNUNET_buffer_write (&buf,
- pos,
- mbl);
- break;
- case 'u':
- {
- unsigned int num;
- uint32_t n32;
- unsigned char res[8];
- size_t rlen;
-
- GNUNET_assert ( (1 ==
- sscanf (pos + 2,
- "%4x",
- &num)) ||
- (1 ==
- sscanf (pos + 2,
- "%4X",
- &num)) );
- mbl = 6;
- n32 = (uint32_t) num;
- rlen = sizeof (res);
- u32_to_u8 (&n32,
- 1,
- res,
- &rlen);
- if ( (1 == rlen) &&
- (res[0] <= 0x1F) )
- {
- lowdump (&buf,
- res[0]);
- }
- else
- {
- GNUNET_buffer_write (&buf,
- (const char *) res,
- rlen);
- }
- }
- break;
- default:
- mbl = 2;
- GNUNET_buffer_write (&buf,
- pos,
- mbl);
- break;
- }
- }
- else
- {
- GNUNET_buffer_write (&buf,
- pos,
- mbl);
- }
- left -= mbl;
- pos += mbl;
- }
-
- /* 0-terminate buffer */
- GNUNET_buffer_write (&buf,
- "",
- 1);
- GNUNET_free (in);
- *inp = GNUNET_buffer_reap (&buf,
- &olen);
- return olen;
-}
-
-
-/**
* Dump the @a json to a string and hash it.
*
* @param json value to hash
@@ -262,7 +98,7 @@ dump_and_hash (const json_t *json,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- len = rfc8785encode (&wire_enc);
+ len = TALER_rfc8785encode (&wire_enc);
if (NULL == salt)
{
GNUNET_CRYPTO_hash (wire_enc,
@@ -1031,7 +867,7 @@ TALER_JSON_canonicalize (const json_t *input)
GNUNET_break (0);
return NULL;
}
- rfc8785encode (&wire_enc);
+ TALER_rfc8785encode (&wire_enc);
return wire_enc;
}
diff --git a/src/util/util.c b/src/util/util.c
index 96d791912..7cd4b0c35 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -25,6 +25,7 @@
#include "taler_util.h"
#include "taler_attributes.h"
#include <gnunet/gnunet_json_lib.h>
+#include <unistr.h>
const char *
@@ -205,6 +206,170 @@ TALER_denom_fee_check_currency (
/**
+ * Dump character in the low range into @a buf
+ * following RFC 8785.
+ *
+ * @param[in,out] buf buffer to modify
+ * @param val value to dump
+ */
+static void
+lowdump (struct GNUNET_Buffer *buf,
+ unsigned char val)
+{
+ char scratch[7];
+
+ switch (val)
+ {
+ case 0x8:
+ GNUNET_buffer_write (buf,
+ "\\b",
+ 2);
+ break;
+ case 0x9:
+ GNUNET_buffer_write (buf,
+ "\\t",
+ 2);
+ break;
+ case 0xA:
+ GNUNET_buffer_write (buf,
+ "\\n",
+ 2);
+ break;
+ case 0xC:
+ GNUNET_buffer_write (buf,
+ "\\f",
+ 2);
+ break;
+ case 0xD:
+ GNUNET_buffer_write (buf,
+ "\\r",
+ 2);
+ break;
+ default:
+ GNUNET_snprintf (scratch,
+ sizeof (scratch),
+ "\\u%04x",
+ (unsigned int) val);
+ GNUNET_buffer_write (buf,
+ scratch,
+ 6);
+ break;
+ }
+}
+
+
+/**
+ * Re-encode string at @a inp to match RFC 8785 (section 3.2.2.2).
+ *
+ * @param[in,out] inp pointer to string to re-encode
+ * @return number of bytes in resulting @a inp
+ */
+size_t
+TALER_rfc8785encode (char **inp)
+{
+ struct GNUNET_Buffer buf = { 0 };
+ size_t left = strlen (*inp) + 1;
+ size_t olen;
+ char *in = *inp;
+ const char *pos = in;
+
+ GNUNET_buffer_prealloc (&buf,
+ left + 40);
+ buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
+ while (1)
+ {
+ int mbl = u8_mblen ((unsigned char *) pos,
+ left);
+ unsigned char val;
+
+ if (0 == mbl)
+ break;
+ val = (unsigned char) *pos;
+ if ( (1 == mbl) &&
+ (val <= 0x1F) )
+ {
+ /* Should not happen, as input is produced by
+ * JSON stringification */
+ GNUNET_break (0);
+ lowdump (&buf,
+ val);
+ }
+ else if ( (1 == mbl) && ('\\' == *pos) )
+ {
+ switch (*(pos + 1))
+ {
+ case '\\':
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ case 'u':
+ {
+ unsigned int num;
+ uint32_t n32;
+ unsigned char res[8];
+ size_t rlen;
+
+ GNUNET_assert ( (1 ==
+ sscanf (pos + 2,
+ "%4x",
+ &num)) ||
+ (1 ==
+ sscanf (pos + 2,
+ "%4X",
+ &num)) );
+ mbl = 6;
+ n32 = (uint32_t) num;
+ rlen = sizeof (res);
+ u32_to_u8 (&n32,
+ 1,
+ res,
+ &rlen);
+ if ( (1 == rlen) &&
+ (res[0] <= 0x1F) )
+ {
+ lowdump (&buf,
+ res[0]);
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ (const char *) res,
+ rlen);
+ }
+ }
+ break;
+ default:
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ }
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ }
+ left -= mbl;
+ pos += mbl;
+ }
+
+ /* 0-terminate buffer */
+ GNUNET_buffer_write (&buf,
+ "",
+ 1);
+ GNUNET_free (in);
+ *inp = GNUNET_buffer_reap (&buf,
+ &olen);
+ return olen;
+}
+
+
+/**
* Hash normalized @a j JSON object or array and
* store the result in @a hc.
*
@@ -221,11 +386,11 @@ TALER_json_hash (const json_t *j,
cstr = json_dumps (j,
JSON_COMPACT | JSON_SORT_KEYS);
GNUNET_assert (NULL != cstr);
- clen = strlen (cstr);
+ clen = TALER_rfc8785encode (&cstr);
GNUNET_CRYPTO_hash (cstr,
clen,
hc);
- free (cstr);
+ GNUNET_free (cstr);
}