implement logic to replace 'true' forgettable salts with random salts, fix object deletion when forgetting

This commit is contained in:
Christian Grothoff 2021-06-16 23:12:21 +02:00
parent 9db945471f
commit 6680f9b4ef
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 121 additions and 5 deletions

View File

@ -198,6 +198,19 @@ TALER_JSON_contract_hash (const json_t *json,
struct GNUNET_HashCode *hc); struct GNUNET_HashCode *hc);
/**
* Take a given contract with "forgettable" fields marked
* but with 'True' instead of a real salt. Replaces all
* 'True' values with proper random salts. Fails if any
* forgettable markers are neither 'True' nor valid salts.
*
* @param[in,out] json JSON to transform
* @return #GNUNET_OK on success
*/
int
TALER_JSON_contract_seed_forgettable (json_t *json);
/** /**
* Mark part of a contract object as 'forgettable'. * Mark part of a contract object as 'forgettable'.
* *

View File

@ -506,9 +506,8 @@ TALER_JSON_contract_part_forget (json_t *json,
} }
/* finally, set 'forgotten' field to null */ /* finally, set 'forgotten' field to null */
if (0 != if (0 !=
json_object_set_new (json, json_object_del (json,
field, field))
json_null ()))
{ {
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
@ -517,6 +516,99 @@ TALER_JSON_contract_part_forget (json_t *json,
} }
/**
* Look over all of the values of a '$forgettable' object. Replace 'True'
* values with proper random salts. Fails if any forgettable values are
* neither 'True' nor valid salts (strings).
*
* @param[in,out] f JSON to transform
* @return #GNUNET_OK on success
*/
static int
seed_forgettable (json_t *f)
{
const char *key;
json_t *val;
json_object_foreach (f,
key,
val)
{
if (json_is_string (val))
continue;
if (json_is_true (val))
{
struct GNUNET_ShortHashCode sh;
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&sh,
sizeof (sh));
json_object_set_new (f,
key,
GNUNET_JSON_from_data_auto (&sh));
continue;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Forgettable field `%s' has invalid value\n",
key);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/**
* Take a given contract with "forgettable" fields marked
* but with 'True' instead of a real salt. Replaces all
* 'True' values with proper random salts. Fails if any
* forgettable markers are neither 'True' nor valid salts.
*
* @param[in,out] json JSON to transform
* @return #GNUNET_OK on success
*/
int
TALER_JSON_contract_seed_forgettable (json_t *json)
{
if (json_is_object (json))
{
const char *key;
json_t *val;
json_object_foreach (json,
key,
val)
{
if (0 == strcmp ("$forgettable",
key))
{
if (GNUNET_OK !=
seed_forgettable (val))
return GNUNET_SYSERR;
continue;
}
if (GNUNET_OK !=
TALER_JSON_contract_seed_forgettable (val))
return GNUNET_SYSERR;
}
}
if (json_is_array (json))
{
size_t index;
json_t *val;
json_array_foreach (json,
index,
val)
{
if (GNUNET_OK !=
TALER_JSON_contract_seed_forgettable (val))
return GNUNET_SYSERR;
}
}
return GNUNET_OK;
}
/** /**
* Parse a json path. * Parse a json path.
* *

View File

@ -96,6 +96,17 @@ test_contract (void)
json_t *c3; json_t *c3;
json_t *c4; json_t *c4;
c1 = json_pack ("{s:s, s:{s:s, s:{s:b}}}",
"k1", "v1",
"k2", "n1", "n2",
/***/ "$forgettable", "n1", true);
GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_seed_forgettable (c1));
GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_hash (c1,
&h1));
json_decref (c1);
c1 = json_pack ("{s:s, s:{s:s, s:{s:s}}}", c1 = json_pack ("{s:s, s:{s:s, s:{s:s}}}",
"k1", "v1", "k1", "v1",
"k2", "n1", "n2", "k2", "n1", "n2",
@ -147,6 +158,7 @@ test_contract (void)
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_part_forget (c1, TALER_JSON_contract_part_forget (c1,
"k2")); "k2"));
json_dumpf (c1, stderr, JSON_INDENT (2));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_hash (c1, TALER_JSON_contract_hash (c1,
&h2)); &h2));
@ -159,7 +171,6 @@ test_contract (void)
return 1; return 1;
} }
c1 = json_pack ("{s:I, s:{s:s}, s:{s:b, s:{s:s}}, s:{s:s}}", c1 = json_pack ("{s:I, s:{s:s}, s:{s:b, s:{s:s}}, s:{s:s}}",
"k1", 1, "k1", 1,
"$forgettable", "k1", "SALT", "$forgettable", "k1", "SALT",
@ -178,7 +189,7 @@ test_contract (void)
sizeof (h1)); sizeof (h1));
if (0 != if (0 !=
strcmp (s, strcmp (s,
"48YVST0SZJXWNG3KAD14SSK3AD0T5V01W5AE6E76DYKMJSC5BQ19M0FZ7CZP5JY26FC4AFXTXRGEVSQ1NSKPQ1DQ4GS9C4SAECG5RZ8")) "VDE8JPX0AEEE3EX1K8E11RYEWSZQKGGZCV6BWTE4ST1C8711P7H850Z7F2Q2HSSYETX87ERC2JNHWB7GTDWTDWMM716VKPSRBXD7SRR"))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid reference hash: %s\n", "Invalid reference hash: %s\n",