exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

tv_age_restriction.c (6980B)


      1 /**
      2  * @file util/tv_age_restriction.c
      3  * @brief Generate test vectors for age restriction
      4  * @author Özgür Kesim
      5  *
      6  * compile in exchange/src/util with
      7  *
      8  * gcc tv_age_restriction.c \
      9  *    -lgnunetutil -lgnunetjson -lsodium -ljansson \
     10  *    -L/usr/lib/x86_64-linux-gnu -lmicrohttpd -ltalerutil \
     11  *    -I../include \
     12  *    -o tv_age_restriction
     13  *
     14  */
     15 #include <gnunet/gnunet_json_lib.h>
     16 #include <gnunet/gnunet_util_lib.h>
     17 #include <jansson.h>
     18 #include <taler/taler_util.h>
     19 #include <taler/taler_crypto_lib.h>
     20 
     21 static struct TALER_AgeMask age_masks[] = {
     22   { .bits = 1
     23             | 1 << 8 | 1 << 14 | 1 << 18 },
     24   { .bits = 1
     25             | 1 << 8 | 1 << 10 | 1 << 12
     26             | 1 << 14 | 1 << 16 | 1 << 18 | 1 << 21 },
     27 };
     28 
     29 extern uint8_t
     30 get_age_group (
     31   const struct TALER_AgeMask *mask,
     32   uint8_t age);
     33 
     34 /**
     35  * Encodes the age mask into a string, like "8:10:12:14:16:18:21"
     36  */
     37 char *
     38 age_mask_to_string (
     39   const struct TALER_AgeMask *mask)
     40 {
     41   uint32_t bits = mask->bits;
     42   unsigned int n = 0;
     43   char *buf = GNUNET_malloc (32 * 3); // max characters possible
     44   char *pos = buf;
     45 
     46   if (NULL == buf)
     47   {
     48     return buf;
     49   }
     50 
     51   while (bits != 0)
     52   {
     53     bits >>= 1;
     54     n++;
     55     if (0 == (bits & 1))
     56     {
     57       continue;
     58     }
     59 
     60     if (n > 9)
     61     {
     62       *(pos++) = '0' + n / 10;
     63     }
     64     *(pos++) = '0' + n % 10;
     65 
     66     if (0 != (bits >> 1))
     67     {
     68       *(pos++) = ':';
     69     }
     70   }
     71   return buf;
     72 }
     73 
     74 
     75 static json_t *
     76 cp_to_j (
     77   const struct GNUNET_HashCode *seed,
     78   struct TALER_AgeCommitmentProof *acp,
     79   uint8_t seq)
     80 {
     81   json_t *j_commitment;
     82   json_t *j_proof;
     83   json_t *j_pubs;
     84   json_t *j_privs;
     85   struct TALER_AgeCommitmentHashP hac = {0};
     86   char buf[256] = {0};
     87 
     88   TALER_age_commitment_hash (&acp->commitment, &hac);
     89 
     90   j_pubs = json_array ();
     91   GNUNET_assert (NULL != j_pubs);
     92   for (unsigned int i = 0; i < acp->commitment.num; i++)
     93   {
     94     json_t *j_pub = GNUNET_JSON_PACK (
     95       GNUNET_JSON_pack_data_auto (NULL,
     96                                   &acp->commitment.keys[i]));
     97     json_array_append_new (j_pubs, j_pub);
     98   }
     99 
    100   j_commitment = GNUNET_JSON_PACK (
    101     GNUNET_JSON_pack_uint64 ("num", acp->commitment.num),
    102     GNUNET_JSON_pack_array_steal ("edx25519_pubs", j_pubs),
    103     GNUNET_JSON_pack_data_auto ("h_age_commitment", &hac));
    104 
    105 
    106   j_privs = json_array ();
    107   GNUNET_assert (NULL != j_privs);
    108   for (unsigned int i = 0; i < acp->proof.num; i++)
    109   {
    110     json_t *j_priv = GNUNET_JSON_PACK (
    111       GNUNET_JSON_pack_data_auto (NULL,
    112                                   &acp->proof.keys[i]));
    113     json_array_append_new (j_privs, j_priv);
    114   }
    115   j_proof = GNUNET_JSON_PACK (
    116     GNUNET_JSON_pack_uint64 ("num", acp->proof.num),
    117     GNUNET_JSON_pack_array_steal ("edx25519_privs", j_privs));
    118 
    119   if (0 == seq)
    120   {
    121     strcpy (buf, "commit()");
    122   }
    123   else
    124   {
    125     sprintf (buf,
    126              "derive_from(%d)",
    127              seq);
    128   }
    129 
    130   return GNUNET_JSON_PACK (
    131     GNUNET_JSON_pack_string ("generated_by", buf),
    132     GNUNET_JSON_pack_data_auto ("seed", seed),
    133     GNUNET_JSON_pack_object_steal ("proof", j_proof),
    134     GNUNET_JSON_pack_object_steal ("commitment", j_commitment));
    135 
    136 };
    137 
    138 static json_t *
    139 generate (
    140   struct TALER_AgeMask *mask)
    141 {
    142   uint8_t age;
    143   json_t *j_commitproofs;
    144   j_commitproofs = json_array ();
    145 
    146   for (age = 0; age < 24; age += 2)
    147   {
    148     json_t *j_top = json_object ();
    149     json_t *j_seq = json_array ();
    150     enum GNUNET_GenericReturnValue ret;
    151     struct TALER_AgeCommitmentProof acp[3] = {0};
    152     uint8_t age_group = get_age_group (mask, age);
    153     struct GNUNET_HashCode seed;
    154 
    155     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    156                                 &seed,
    157                                 sizeof(seed));
    158 
    159     json_object_set (j_top,
    160                      "committed_age",
    161                      json_integer (age));
    162 
    163     ret = TALER_age_restriction_commit (mask,
    164                                         age,
    165                                         &seed,
    166                                         &acp[0]);
    167 
    168     GNUNET_assert (GNUNET_OK == ret);
    169 
    170     /* Also derive two more commitments right away */
    171     for (uint8_t i = 0; i<2; i++)
    172     {
    173       struct GNUNET_HashCode salt;
    174       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    175                                   &salt,
    176                                   sizeof (salt));
    177       GNUNET_assert (GNUNET_OK ==
    178                      TALER_age_commitment_derive (&acp[i],
    179                                                   &salt,
    180                                                   &acp[i + 1]));
    181     }
    182 
    183     for (uint8_t i = 0; i < 3; i++)
    184     {
    185       json_t *j_cp = cp_to_j (&seed, &acp[i], i);
    186       json_t *j_attestations = json_array ();
    187 
    188       for (uint8_t min = 0; min < 22; min++)
    189       {
    190         json_t *j_attest = json_object ();
    191         json_t *j_reason;
    192         uint8_t min_group = get_age_group (mask, min);
    193         struct TALER_AgeAttestationP at = {0};
    194 
    195         json_object_set (j_attest,
    196                          "required_minimum_age",
    197                          json_integer (min));
    198         json_object_set (j_attest,
    199                          "calculated_age_group",
    200                          json_integer (min_group));
    201 
    202         ret = TALER_age_commitment_attest (&acp[i],
    203                                            min,
    204                                            &at);
    205 
    206 
    207         if (0 == min_group)
    208           j_reason =  json_string (
    209             "not required: age group is 0");
    210         else if (min_group > age_group)
    211           j_reason = json_string (
    212             "not applicable: committed age too small");
    213         else
    214           j_reason = GNUNET_JSON_PACK (
    215             GNUNET_JSON_pack_data_auto (NULL, &at));
    216 
    217         json_object_set (j_attest,
    218                          "attestation",
    219                          j_reason);
    220 
    221         json_array_append_new (j_attestations,
    222                                j_attest);
    223 
    224       }
    225 
    226       json_object_set (j_cp, "attestations", j_attestations);
    227       json_array_append (j_seq,  j_cp);
    228 
    229       TALER_age_commitment_proof_free (&acp[i]);
    230     }
    231 
    232     json_object_set (j_top, "commitment_proof_attestation_seq", j_seq);
    233     json_array_append_new (j_commitproofs, j_top);
    234   }
    235 
    236   return j_commitproofs;
    237 }
    238 
    239 
    240 int
    241 main (int argc,
    242       const char *const argv[])
    243 {
    244   (void) argc;
    245   (void) argv;
    246   json_t *j_data = json_array ();
    247   for (unsigned int i = 0; i < 2; i++)
    248   {
    249     struct TALER_AgeMask mask = age_masks[i];
    250     json_t *j_test = json_object ();
    251     json_object_set (j_test,
    252                      "age_groups",
    253                      json_string (age_mask_to_string (&mask)));
    254     json_object_set (j_test,
    255                      "age_mask",
    256                      json_integer (mask.bits));
    257     json_object_set (j_test,
    258                      "test_data",
    259                      generate (&mask));
    260     json_array_append_new (j_data, j_test);
    261   }
    262   printf ("%s\n", json_dumps (j_data, JSON_INDENT (2)
    263                               | JSON_COMPACT));
    264 
    265   json_decref (j_data);
    266   return 0;
    267 }
    268 
    269 
    270 /* end of tv_age_restriction.c */