From edd2646a8691b653b84d87b6fa49b7ded464a03c Mon Sep 17 00:00:00 2001 From: swrup Date: Fri, 27 Feb 2026 20:28:56 +0100 Subject: [PATCH] refacto verify_denomination/signkey --- src/api.ml | 25 ++++++++ src/denomination.ml | 17 ++++++ src/http_management.ml | 87 ++++----------------------- src/keys.ml | 30 ++++++---- src/signkey.ml | 10 ++++ test/validate_response.ml | 121 ++++++++++++-------------------------- 6 files changed, 120 insertions(+), 170 deletions(-) diff --git a/src/api.ml b/src/api.ml index 9f3b99d0..dcbf036d 100644 --- a/src/api.ml +++ b/src/api.ml @@ -612,6 +612,31 @@ module GlobalFees = struct master_sig: GlobalFees.t; } + let verify_global_fees ~key + { + start_date; + end_date; + history_fee; + account_fee; + purse_fee; + history_expiration; + purse_account_limit; + purse_timeout; + master_sig; + } = + let open Signatures.GlobalFees in + verify key master_sig + { + start_date; + end_date; + purse_timeout; + history_expiration; + history_fee; + account_fee; + purse_fee; + purse_account_limit; + } + let jsont = let make start_date end_date history_fee account_fee purse_fee history_expiration purse_account_limit purse_timeout master_sig = diff --git a/src/denomination.ml b/src/denomination.ml index 710f8921..e1aabbc8 100644 --- a/src/denomination.ml +++ b/src/denomination.ml @@ -16,6 +16,23 @@ type t = { master_sig: Signatures.DenominationKeyValidity.t; } +let verify_denomination_key_validity ~key dn = + let open Signatures.DenominationKeyValidity in + verify key dn.master_sig + { + R.master= 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; + } + let make_denom_group_sorted denominations = let open Syntax in (* use hashtbl to re-group denoms *) diff --git a/src/http_management.ml b/src/http_management.ml index f1ef75b6..f1b67201 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -16,68 +16,26 @@ module Keys_get = struct end module Keys_post = struct - let verify_fdn (module Keys : Keys.S) - DenomSignature.{ h_denom_pub; master_sig } = - let open FutureDenom in - let open Signatures.DenominationKeyValidity in - let* fdn = Keys.find_future_denomination h_denom_pub in - verify Config.master_public_key master_sig - { - R.master= Config.master_public_key; - start= fdn.stamp_start; - expire_withdraw= fdn.stamp_expire_withdraw; - expire_spend= fdn.stamp_expire_deposit; - expire_legal= fdn.stamp_expire_legal; - value= fdn.value; - fee_withdraw= fdn.fee_withdraw; - fee_deposit= fdn.fee_deposit; - fee_refresh= fdn.fee_refresh; - fee_refund= fdn.fee_refund; - denom_hash= h_denom_pub; - } - - let verify_fsk (module Keys : Keys.S) SignKeySignature.{ key; master_sig } = - let open Signatures.ExchangeSigningKeyValidity in - let* fsk = Keys.find_future_signkey key in - verify Config.master_public_key master_sig - { - R.start= fsk.stamp_start; - expire= fsk.stamp_expire; - end_= fsk.stamp_end; - signkey_pub= key; - } - - let verify keys MasterSignatures.{ denom_sigs; signkey_sigs } = - let* () = list_iter (verify_fsk keys) signkey_sigs in - let* () = list_iter (verify_fdn keys) denom_sigs in + let verify (module Keys : Keys.S) + MasterSignatures.{ denom_sigs; signkey_sigs } = + let* () = list_iter Keys.verify_future_signkey signkey_sigs in + let* () = list_iter Keys.verify_future_denomination denom_sigs in Ok () - let do_ ~db_conn:_ (module Keys : Keys.S) - MasterSignatures.{ denom_sigs; signkey_sigs } = - let* () = - list_iter - (fun SignKeySignature.{ key; master_sig } -> - Keys.certify_future_signkey key master_sig) - signkey_sigs - in - let* () = - list_iter - (fun DenomSignature.{ h_denom_pub; master_sig } -> - Keys.certify_future_denomination h_denom_pub master_sig) - denom_sigs - in + let do_ (module Keys : Keys.S) MasterSignatures.{ denom_sigs; signkey_sigs } = + let* () = list_iter Keys.certify_future_signkey signkey_sigs in + let* () = list_iter Keys.certify_future_denomination denom_sigs in Ok () let jsont = MasterSignatures.jsont let f req server _env = Logs.info (fun m -> m "POST /management/keys/"); - let db_conn = Vif.Server.device Devices.db_connection server in let keys = Vif.Server.device Devices.keys server in let res = let* v = Vif.Request.of_json req |> unwrap_err_msg in let* () = verify keys v in - let* () = do_ ~db_conn keys v in + let* () = do_ keys v in Ok () in Respond.result_no_content res req @@ -292,31 +250,7 @@ module Wire_fee = struct end module Global_fees = struct - let verify (module Keys : Keys.S) - GlobalFees. - { - start_date; - end_date; - history_fee; - account_fee; - purse_fee; - history_expiration; - purse_account_limit; - purse_timeout; - master_sig; - } = - let open Signatures.GlobalFees in - verify Config.master_public_key master_sig - { - start_date; - end_date; - purse_timeout; - history_expiration; - history_fee; - account_fee; - purse_fee; - purse_account_limit; - } + let verify v = GlobalFees.verify_global_fees ~key:Config.master_public_key v let do_ ~db_conn v = let* global_fees = @@ -351,11 +285,10 @@ module Global_fees = struct and once set for a timeframe, it should not change. *) let f req server _env = Logs.info (fun m -> m "POST /management/global-fees/"); - let keys = Vif.Server.device Devices.keys server in let db_conn = Vif.Server.device Devices.db_connection server in let res = let* v = Vif.Request.of_json req |> unwrap_err_msg in - let* () = verify keys v in + let* () = verify v in let* () = do_ ~db_conn v in Ok () in diff --git a/src/keys.ml b/src/keys.ml index ef67bb0b..09d6da82 100644 --- a/src/keys.ml +++ b/src/keys.ml @@ -11,15 +11,11 @@ module type S = sig val find_denomination : denom_hash -> Denomination.t option result val signkeys : unit -> Signkey.t list result val denominations : unit -> Denomination.t list result - val find_future_signkey : eddsa_pub -> Api.FutureSignKey.t result - val find_future_denomination : denom_hash -> Api.FutureDenom.t result val make_future_keys_response : unit -> Api.FutureKeysResponse.t result - - val certify_future_signkey : - eddsa_pub -> Signatures.ExchangeSigningKeyValidity.t -> unit result - - val certify_future_denomination : - denom_hash -> Signatures.DenominationKeyValidity.t -> unit result + val verify_future_signkey : Api.SignKeySignature.t -> unit result + val verify_future_denomination : Api.DenomSignature.t -> unit result + val certify_future_signkey : Api.SignKeySignature.t -> unit result + val certify_future_denomination : Api.DenomSignature.t -> unit result val revoke_signkey : eddsa_pub -> Signatures.MasterSigningKeyRevocation.t -> unit result @@ -277,7 +273,20 @@ module Make (Conn : Pg.CONN) : S = struct master_sig; } - let certify_future_signkey pub master_sig = + let verify_future_signkey Api.SignKeySignature.{ key; master_sig } = + let* fsk = find_future_signkey key in + let sk = sk_of_future_sk fsk master_sig in + Signkey.verify_exchange_signing_key_validity ~key:Config.master_public_key + sk + + let verify_future_denomination Api.DenomSignature.{ h_denom_pub; master_sig } + = + let* fdn = find_future_denomination h_denom_pub in + let dn = dn_of_future_dn fdn h_denom_pub master_sig in + Denomination.verify_denomination_key_validity ~key:Config.master_public_key + dn + + let certify_future_signkey Api.SignKeySignature.{ key= pub; master_sig } = match Sm_eddsa.find_key pub with | None -> Error "future signkey not found" | Some (pub, (t1, t2)) -> ( @@ -295,7 +304,8 @@ module Make (Conn : Pg.CONN) : S = struct m "certified signkey `%s`" (EddsaPublicKey.to_b32 sk.pub)); ()) - let certify_future_denomination h_pub master_sig = + let certify_future_denomination + Api.DenomSignature.{ h_denom_pub= h_pub; master_sig } = match Sm_rsa.find_key h_pub with | None -> Error "future denomination not found" | Some (h_pub, (section_name, pub, t1)) -> ( diff --git a/src/signkey.ml b/src/signkey.ml index 8d58e117..78e4ea46 100644 --- a/src/signkey.ml +++ b/src/signkey.ml @@ -8,5 +8,15 @@ type t = { master_sig: Signatures.ExchangeSigningKeyValidity.t; } +let verify_exchange_signing_key_validity ~key sk = + let open Signatures.ExchangeSigningKeyValidity in + verify key sk.master_sig + { + R.start= sk.stamp_start; + expire= sk.stamp_expire; + end_= sk.stamp_end; + signkey_pub= sk.pub; + } + let is_valid_at ~timestamp sk = Timestamp.geq sk.stamp_start timestamp && Timestamp.lt timestamp sk.stamp_end diff --git a/test/validate_response.ml b/test/validate_response.ml index c1b7795c..6248acee 100644 --- a/test/validate_response.ml +++ b/test/validate_response.ml @@ -34,30 +34,21 @@ let keys content = closing_fee; }) in + (*Fmt.pr "OK wire_fees@.";*) + let sk_l = List.map SignKey.to_signkey v.signkeys in let* () = - let open SignKey in - v.signkeys + sk_l |> list_iter - (fun { key; stamp_start; stamp_expire; stamp_end; master_sig } -> - let open Signatures.ExchangeSigningKeyValidity in - verify v.master_public_key master_sig - { - R.start= stamp_start; - expire= stamp_expire; - end_= stamp_end; - signkey_pub= key; - }) + (Signkey.verify_exchange_signing_key_validity ~key:v.master_public_key) in + (*Fmt.pr "OK signkeys@.";*) let* () = - let opt = - List.find_opt (fun sk -> sk.SignKey.key = v.exchange_pub) v.signkeys - in + let opt = List.find_opt (fun sk -> sk.Signkey.pub = v.exchange_pub) sk_l in match opt with | 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 *) let now = Timestamp.of_ptime (Ptime_clock.now ()) in if Signkey.is_valid_at ~timestamp:now sk then Ok () @@ -72,27 +63,13 @@ let keys content = hc= Denomination.hash_over_master_sigs v.denominations; } in + (*Fmt.pr "OK exchange_pub@.";*) let denom_l = v.denominations |> Denomination.denoms_of_denomgroups in let* () = - 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; - }) + |> list_iter + (Denomination.verify_denomination_key_validity ~key:v.master_public_key) in let* () = let last_issue_date = @@ -103,73 +80,51 @@ let keys content = if last_issue_date = v.list_issue_date then Ok () else Fmt.error "list_issue_date is wrong" in + (*Fmt.pr "OK denominations@.";*) let* () = v.global_fees - |> list_iter - (fun - GlobalFees. - { - start_date; - end_date; - history_fee; - account_fee; - purse_fee; - history_expiration; - purse_account_limit; - purse_timeout; - master_sig; - } - -> - let open Signatures.GlobalFees in - verify v.master_public_key master_sig - { - start_date; - end_date; - purse_timeout; - history_expiration; - history_fee; - account_fee; - purse_fee; - purse_account_limit; - }) + |> list_iter (GlobalFees.verify_global_fees ~key:v.master_public_key) in + (*Fmt.pr "OK global_fees@.";*) let* () = (* TODO O(n^2) *) v.auditors - |> list_iter + |> List.concat_map (fun AuditorKeys. { auditor_pub; auditor_url; auditor_name= _; denomination_keys } -> let auditor_url_hash = Hash.H64.hash auditor_url in denomination_keys - |> list_iter + |> List.map (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; - })) + (denom_pub_h, auditor_url_hash, auditor_pub, auditor_sig))) + |> list_iter + (fun (denom_pub_h, auditor_url_hash, auditor_pub, auditor_sig) -> + let open Denomination in + denom_l |> List.find_opt (fun dn -> dn.h_pub = denom_pub_h) + |> function + | 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= dn.h_pub; + }) in + (*Fmt.pr "OK auditors@.";*) Ok ()