From d2e546571c1f68c30b07920ff8dfe2b1696140c5 Mon Sep 17 00:00:00 2001 From: swrup Date: Fri, 27 Feb 2026 19:38:34 +0100 Subject: [PATCH] + validate auditors --- src/denomination.ml | 49 ++++++++++++++++ test/validate_response.ml | 115 +++++++++++++++++++------------------- 2 files changed, 107 insertions(+), 57 deletions(-) diff --git a/src/denomination.ml b/src/denomination.ml index 6f7cf827..710f8921 100644 --- a/src/denomination.ml +++ b/src/denomination.ml @@ -111,6 +111,55 @@ let make_denom_group_sorted denominations = in l +let denoms_of_denomgroups l = + let open Api in + l + |> List.concat_map + (fun + (DenomGroup.Rsa + RsaDenomGroup. + { + denoms; + value; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + }) + -> + let open RsaDenom in + denoms + |> List.map + (fun + { + rsa_pub; + master_sig; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + lost= _; + } + -> + let h_pub = + DenominationHash.hash (Crypto.RsaPublicKey.to_octets rsa_pub) + in + { + pub= rsa_pub; + value; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + age_mask= 0; + h_pub; + master_sig; + })) + let hash_over_master_sigs denominations = denominations |> List.map (fun (Api.DenomGroup.Rsa g) -> g.Api.RsaDenomGroup.denoms) diff --git a/test/validate_response.ml b/test/validate_response.ml index 78b484a9..c1b7795c 100644 --- a/test/validate_response.ml +++ b/test/validate_response.ml @@ -58,7 +58,7 @@ let keys content = | None -> Fmt.error "exchange_pub is not in signkeys list" | Some sk -> let sk = SignKey.to_signkey sk in - (* todo will need to fake time to validate expired data *) + (* TODO will need to fake time to validate expired data *) let now = Timestamp.of_ptime (Ptime_clock.now ()) in if Signkey.is_valid_at ~timestamp:now sk then Ok () else Fmt.error "exchange_pub is not valid at the current time" @@ -73,71 +73,37 @@ let keys content = } in - let last_issue_date = ref Timestamp.zero in + let denom_l = v.denominations |> Denomination.denoms_of_denomgroups in let* () = - (* TODO parse CS *) - v.denominations - |> list_iter - (fun - (DenomGroup.Rsa - RsaDenomGroup. - { - denoms; - value; - fee_withdraw; - fee_deposit; - fee_refresh; - fee_refund; - }) - -> - let open RsaDenom in - denoms - |> list_iter - (fun - { - rsa_pub; - master_sig; - stamp_start; - stamp_expire_withdraw; - stamp_expire_deposit; - stamp_expire_legal; - lost= _; - } - -> - last_issue_date := Timestamp.max !last_issue_date stamp_start; - let denom_hash = - DenominationHash.hash - (Crypto.RsaPublicKey.to_octets rsa_pub) - in - let open Signatures.DenominationKeyValidity in - verify v.master_public_key master_sig - { - R.master= v.master_public_key; - start= stamp_start; - expire_withdraw= stamp_expire_withdraw; - expire_spend= stamp_expire_deposit; - expire_legal= stamp_expire_legal; - value; - fee_withdraw; - fee_deposit; - fee_refresh; - fee_refund; - denom_hash; - })) + let open Denomination in + denom_l + |> list_iter (fun dn -> + let open Signatures.DenominationKeyValidity in + verify v.master_public_key dn.master_sig + { + R.master= v.master_public_key; + start= dn.stamp_start; + expire_withdraw= dn.stamp_expire_withdraw; + expire_spend= dn.stamp_expire_deposit; + expire_legal= dn.stamp_expire_legal; + value= dn.value; + fee_withdraw= dn.fee_withdraw; + fee_deposit= dn.fee_deposit; + fee_refresh= dn.fee_refresh; + fee_refund= dn.fee_refund; + denom_hash= dn.h_pub; + }) in let* () = let last_issue_date = - v.denominations - |> List.concat_map (fun (DenomGroup.Rsa rsa_denom_group) -> - rsa_denom_group.denoms) - |> List.map (fun rsa_denom -> rsa_denom.RsaDenom.stamp_start) + denom_l + |> List.map (fun dn -> dn.Denomination.stamp_start) |> List.fold_left Timestamp.max Timestamp.zero in if last_issue_date = v.list_issue_date then Ok () else Fmt.error "list_issue_date is wrong" in - (* validate global-fees *) let* () = v.global_fees |> list_iter @@ -169,7 +135,42 @@ let keys content = }) in - (* validate auditors *) + let* () = + (* TODO O(n^2) *) + v.auditors + |> list_iter + (fun + AuditorKeys. + { auditor_pub; auditor_url; auditor_name= _; denomination_keys } + -> + let auditor_url_hash = Hash.H64.hash auditor_url in + denomination_keys + |> list_iter + (fun AuditorDenominationKey.{ denom_pub_h; auditor_sig } -> + let open Denomination in + let opt = + denom_l |> List.find_opt (fun dn -> dn.h_pub = denom_pub_h) + in + match opt with + | None -> Fmt.error "auditor denomination key not found" + | Some dn -> + let open Signatures.ExchangeKeyValidity in + verify auditor_pub auditor_sig + { + auditor_url_hash; + master= auditor_pub; + start= dn.stamp_start; + expire_withdraw= dn.stamp_expire_withdraw; + expire_spend= dn.stamp_expire_deposit; + expire_legal= dn.stamp_expire_legal; + value= dn.value; + fee_withdraw= dn.fee_withdraw; + fee_deposit= dn.fee_deposit; + fee_refresh= dn.fee_refresh; + denom_hash= denom_pub_h; + })) + in + Ok () (* --- *)