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