implementing retrieval of auditor information from /keys in mint API (with updated specification) - #3847

This commit is contained in:
Christian Grothoff 2015-09-19 16:11:31 +02:00
parent fb14af5ba8
commit 7fbae8f69f
3 changed files with 258 additions and 13 deletions

View File

@ -149,6 +149,11 @@ struct TALER_MINT_DenomPublicKey
*/
struct TALER_DenominationPublicKey key;
/**
* The hash of the public key.
*/
struct GNUNET_HashCode h_key;
/**
* Timestamp indicating when the denomination key becomes valid
*/
@ -165,6 +170,15 @@ struct TALER_MINT_DenomPublicKey
*/
struct GNUNET_TIME_Absolute deposit_valid_until;
/**
* When do signatures with this denomination key become invalid?
* After this point, these signatures cannot be used in (legal)
* disputes anymore, as the Mint is then allowed to destroy its side
* of the evidence. @e expire_legal is expected to be significantly
* larger than @e expire_spend (by a year or more).
*/
struct GNUNET_TIME_Absolute expire_legal;
/**
* The value of this denomination
*/
@ -204,6 +218,8 @@ struct TALER_MINT_AuditorInformation
* that website. We expect that in practice software is going to
* often ship with an initial list of accepted auditors, just like
* browsers ship with a CA root store.
*
* This field may be NULL. (#3987).
*/
const char *auditor_url;
@ -218,7 +234,7 @@ struct TALER_MINT_AuditorInformation
* elements point to the same locations as the entries
* in the key's main `denom_keys` array.
*/
struct TALER_MINT_DenomPublicKey *const*denom_keys;
const struct TALER_MINT_DenomPublicKey **denom_keys;
};
@ -246,7 +262,7 @@ struct TALER_MINT_Keys
/**
* Array of the keys of the auditors of the mint.
*/
struct TALER_AuditorPublicKeyP *auditors;
struct TALER_MINT_AuditorInformation *auditors;
/**
* Length of the @e sign_keys array.
@ -353,6 +369,18 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
const struct TALER_DenominationPublicKey *pk);
/**
* Obtain the denomination key details from the mint.
*
* @param keys the mint's key set
* @param hc hash of the public key of the denomination to lookup
* @return details about the given denomination key
*/
const struct TALER_MINT_DenomPublicKey *
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
const struct GNUNET_HashCode *hc);
/* ********************* /wire *********************** */

View File

@ -653,13 +653,73 @@ struct TALER_MintKeyValidityPS
struct TALER_MasterPublicKeyP master;
/**
* Array of hash(es) of the mint's denomination keys.
* Specifically, this is the hash over the
* `struct TALER_DenominationKeyValidityPS`, not just
* the public key (as the auditor needs to check against
* the correct valuations and fee structure).
* Start time of the validity period for this key.
*/
/* struct GNUNET_HashCode h_dks; */
struct GNUNET_TIME_AbsoluteNBO start;
/**
* The mint will sign fresh coins between @e start and this time.
* @e expire_withdraw will be somewhat larger than @e start to
* ensure a sufficiently large anonymity set, while also allowing
* the Mint to limit the financial damage in case of a key being
* compromised. Thus, mints with low volume are expected to have a
* longer withdraw period (@e expire_withdraw - @e start) than mints
* with high transaction volume. The period may also differ between
* types of coins. A mint may also have a few denomination keys
* with the same value with overlapping validity periods, to address
* issues such as clock skew.
*/
struct GNUNET_TIME_AbsoluteNBO expire_withdraw;
/**
* Coins signed with the denomination key must be spent or refreshed
* between @e start and this expiration time. After this time, the
* mint will refuse transactions involving this key as it will
* "drop" the table with double-spending information (shortly after)
* this time. Note that wallets should refresh coins significantly
* before this time to be on the safe side. @e expire_spend must be
* significantly larger than @e expire_withdraw (by months or even
* years).
*/
struct GNUNET_TIME_AbsoluteNBO expire_spend;
/**
* When do signatures with this denomination key become invalid?
* After this point, these signatures cannot be used in (legal)
* disputes anymore, as the Mint is then allowed to destroy its side
* of the evidence. @e expire_legal is expected to be significantly
* larger than @e expire_spend (by a year or more).
*/
struct GNUNET_TIME_AbsoluteNBO expire_legal;
/**
* The value of the coins signed with this denomination key.
*/
struct TALER_AmountNBO value;
/**
* The fee the mint charges when a coin of this type is withdrawn.
* (can be zero).
*/
struct TALER_AmountNBO fee_withdraw;
/**
* The fee the mint charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_AmountNBO fee_deposit;
/**
* The fee the mint charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO fee_refresh;
/**
* Hash code of the denomination public key. (Used to avoid having
* the variable-size RSA key in this struct.)
*/
struct GNUNET_HashCode denom_hash GNUNET_PACKED;
};

View File

@ -325,9 +325,11 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
&denom_key_issue.denom_hash,
sizeof (struct GNUNET_HashCode));
denom_key->key.rsa_public_key = pk;
denom_key->h_key = denom_key_issue.denom_hash;
denom_key->valid_from = valid_from;
denom_key->withdraw_valid_until = withdraw_valid_until;
denom_key->deposit_valid_until = deposit_valid_until;
denom_key->expire_legal = expire_legal;
denom_key->value = value;
denom_key->fee_withdraw = fee_withdraw;
denom_key->fee_deposit = fee_deposit;
@ -340,6 +342,116 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
}
/**
* Parse a mint's auditor information encoded in JSON.
*
* @param[out] auditor where to return the result
* @param[in] auditor_obj json to parse
* @param key_data information about denomination keys
* @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
* invalid or the json malformed.
*/
static int
parse_json_auditor (struct TALER_MINT_AuditorInformation *auditor,
json_t *auditor_obj,
const struct TALER_MINT_Keys *key_data)
{
json_t *keys;
json_t *key;
unsigned int len;
unsigned int off;
unsigned int i;
struct TALER_MintKeyValidityPS kv;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("auditor_pub",
&auditor->auditor_pub),
MAJ_spec_json ("denomination_keys",
&keys),
MAJ_spec_end
};
auditor->auditor_url = NULL; /* #3987 */
if (GNUNET_OK !=
MAJ_parse_json (auditor_obj,
spec))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
kv.master = key_data->master_pub;
len = json_array_size (keys);
auditor->denom_keys = GNUNET_new_array (len,
const struct TALER_MINT_DenomPublicKey *);
i = 0;
off = 0;
json_array_foreach (keys, i, key) {
struct TALER_AuditorSignatureP auditor_sig;
struct GNUNET_HashCode denom_h;
const struct TALER_MINT_DenomPublicKey *dk;
unsigned int j;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("denom_pub_h",
&denom_h),
MAJ_spec_fixed_auto ("auditor_sig",
&auditor_sig),
MAJ_spec_end
};
if (GNUNET_OK !=
MAJ_parse_json (key,
spec))
{
GNUNET_break_op (0);
continue;
}
dk = NULL;
for (j=0;j<key_data->num_denom_keys;j++)
{
if (0 == memcmp (&denom_h,
&key_data->denom_keys[j].h_key,
sizeof (struct GNUNET_HashCode)))
{
dk = &key_data->denom_keys[j];
break;
}
}
if (NULL == dk)
{
GNUNET_break_op (0);
continue;
}
kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
kv.expire_spend = GNUNET_TIME_absolute_hton (dk->deposit_valid_until);
kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
TALER_amount_hton (&kv.value,
&dk->value);
TALER_amount_hton (&kv.fee_withdraw,
&dk->fee_withdraw);
TALER_amount_hton (&kv.fee_deposit,
&dk->fee_deposit);
TALER_amount_hton (&kv.fee_refresh,
&dk->fee_refresh);
kv.denom_hash = dk->h_key;
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_MINT_KEYS,
&kv.purpose,
&auditor_sig.eddsa_sig,
&auditor->auditor_pub.eddsa_pub))
{
GNUNET_break_op (0);
continue;
}
auditor->denom_keys[off] = dk;
off++;
}
auditor->num_denom_keys = off;
return GNUNET_OK;
}
/**
* Decode the JSON in @a resp_obj from the /keys response and store the data
* in the @a key_data.
@ -394,8 +506,8 @@ decode_keys_json (json_t *resp_obj,
EXITIF (0 == (key_data->num_sign_keys =
json_array_size (sign_keys_array)));
key_data->sign_keys
= GNUNET_malloc (sizeof (struct TALER_MINT_SigningPublicKey)
* key_data->num_sign_keys);
= GNUNET_new_array (key_data->num_sign_keys,
struct TALER_MINT_SigningPublicKey);
index = 0;
json_array_foreach (sign_keys_array, index, sign_key_obj) {
EXITIF (GNUNET_SYSERR ==
@ -415,8 +527,8 @@ decode_keys_json (json_t *resp_obj,
json_object_get (resp_obj, "denoms")));
EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
EXITIF (0 == (key_data->num_denom_keys = json_array_size (denom_keys_array)));
key_data->denom_keys = GNUNET_malloc (sizeof (struct TALER_MINT_DenomPublicKey)
* key_data->num_denom_keys);
key_data->denom_keys = GNUNET_new_array (key_data->num_denom_keys,
struct TALER_MINT_DenomPublicKey);
index = 0;
json_array_foreach (denom_keys_array, index, denom_key_obj) {
EXITIF (GNUNET_SYSERR ==
@ -427,7 +539,30 @@ decode_keys_json (json_t *resp_obj,
}
}
/* FIXME: parse the auditor keys (#3847) */
/* parse the auditor information */
{
json_t *auditors_array;
json_t *auditor_info;
unsigned int len;
unsigned int index;
EXITIF (NULL == (auditors_array =
json_object_get (resp_obj, "auditors")));
EXITIF (JSON_ARRAY != json_typeof (auditors_array));
len = json_array_size (auditors_array);
if (0 != len)
{
key_data->auditors = GNUNET_new_array (len,
struct TALER_MINT_AuditorInformation);
index = 0;
json_array_foreach (auditors_array, index, auditor_info) {
EXITIF (GNUNET_SYSERR ==
parse_json_auditor (&key_data->auditors[index],
auditor_info,
key_data));
}
}
}
/* Validate signature... */
ks.purpose.size = htonl (sizeof (ks));
@ -708,6 +843,28 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
}
/**
* Obtain the denomination key details from the mint.
*
* @param keys the mint's key set
* @param hc hash of the public key of the denomination to lookup
* @return details about the given denomination key
*/
const struct TALER_MINT_DenomPublicKey *
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
const struct GNUNET_HashCode *hc)
{
unsigned int i;
for (i=0;i<keys->num_denom_keys;i++)
if (0 == memcmp (hc,
&keys->denom_keys[i].h_key,
sizeof (struct GNUNET_HashCode)))
return &keys->denom_keys[i];
return NULL;
}
/**
* Obtain the keys from the mint.
*