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 */