diff --git a/src/http_management.ml b/src/http_management.ml index 9d79864a..72abe7e1 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -3,93 +3,12 @@ open Api open Hash module Keys_get = struct - let mk_future_denom (module Sm : Secmod.S) ~section_name - ({ - pub; - value; - stamp_start; - stamp_expire_withdraw; - stamp_expire_deposit; - stamp_expire_legal; - fee_withdraw; - fee_deposit; - fee_refresh; - fee_refund; - age_mask; - h_pub; - master_sig= _; - revoked_sig= _; - } : - Denomination.t) = - let denom_pub = - DenominationKey.of_rsa RsaDenominationKey.{ age_mask; rsa_pub= pub } - in - let denom_secmod_sig = - let open Signatures.DenominationKeyAnnouncement in - let h_denom_pub = h_pub in - let h_section_name = Hash.Cstring.H64.hash section_name in - let anchor_time = stamp_start in - let duration_withdraw = - Timestamp.diff stamp_start stamp_expire_withdraw - in - sign_f ~f:Sm.sign_with_sm_key - { h_denom_pub; h_section_name; anchor_time; duration_withdraw } - in - FutureDenom. - { - section_name; - value; - stamp_start; - stamp_expire_withdraw; - stamp_expire_deposit; - stamp_expire_legal; - denom_pub; - fee_withdraw; - fee_deposit; - fee_refresh; - fee_refund; - denom_secmod_sig; - } - - let mk_future_signkey (module Sm : Secmod.S) - ({ - pub; - stamp_start; - stamp_expire; - stamp_end; - master_sig= _; - revoked_sig= _; - } : - Signkey.t) = - let signkey_secmod_sig = - let open Signatures.SigningKeyAnnouncement in - let exchange_pub = pub in - let anchor_time = stamp_start in - let duration = Timestamp.diff stamp_start stamp_expire in - sign_f ~f:Sm.sign_with_sm_key { exchange_pub; anchor_time; duration } - in - FutureSignKey. - { key= pub; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig } - let mk_future_keys_response (module Sm : Secmod.S) = - let future_signkeys = - Sm.get_signkeys_data () - |> List.filter (fun k -> Option.is_none k.Signkey.master_sig) - |> List.map (fun signkey -> mk_future_signkey (module Sm) signkey) - in - let future_denoms = - Sm.get_denoms_data () - |> List.filter (fun k -> Option.is_none k.Denomination.master_sig) - |> List.map (fun dn_data -> - let opt = Sm.find_denom_section_name dn_data.Denomination.h_pub in - match opt with - | None -> Fmt.failwith "section_name not found." - | Some section_name -> - mk_future_denom (module Sm) ~section_name dn_data) - in + let future_signkeys = Sm.get_future_signkeys () in + let future_denoms = Sm.get_future_denominations () in let master_pub = Config.Exchange.master_public_key in - let denom_secmod_public_key = Sm.get_sm_key_pub () in - let signkey_secmod_public_key = Sm.get_sm_key_pub () in + let denom_secmod_public_key = Sm.sm_pubkey in + let signkey_secmod_public_key = Sm.sm_pubkey in FutureKeysResponse. { future_denoms; @@ -144,7 +63,7 @@ module Keys_post = struct let verify_signkey_signature (module Sm : Secmod.S) SignKeySignature.{ key; master_sig } = let* signkey = - match Sm.find_signkey_data key with + match Sm.find_signkey key with | None -> Fmt.error "404 not found, One of the keys for which a signature was provided \ @@ -170,18 +89,18 @@ module Keys_post = struct let do_ ~db_conn:_ (module Sm : Secmod.S) MasterSignatures.{ denom_sigs; signkey_sigs } = let* () = - signkey_sigs - |> List.map (fun SignKeySignature.{ key; master_sig } -> - (key, master_sig)) - |> Sm.add_signkey_master_signatures + list_iter + (fun SignKeySignature.{ key; master_sig } -> + Sm.certify_future_signkey key master_sig) + signkey_sigs in let* () = - denom_sigs - |> List.map (fun DenomSignature.{ h_denom_pub; master_sig } -> - (h_denom_pub, master_sig)) - |> Sm.add_denom_master_signatures + list_iter + (fun DenomSignature.{ h_denom_pub; master_sig } -> + Sm.certify_future_denomination h_denom_pub master_sig) + denom_sigs in - let* () = Sm.store () in + let* () = Sm.save () in Ok () let jsont = MasterSignatures.jsont diff --git a/src/secmod.ml b/src/secmod.ml index b61f2f5e..39c4374b 100644 --- a/src/secmod.ml +++ b/src/secmod.ml @@ -48,7 +48,8 @@ module Make (Conn : Pg.CONN) = struct type dn = Denomination.t type future_dn = Api.FutureDenom.t - (* TODO use lock! *) + (* TODO ! use lock *) + (* not sure what to do with coin section_name, rm if possible *) type t = { sm_key: eddsa_priv; sm_pubkey: eddsa_pub; @@ -63,24 +64,25 @@ module Make (Conn : Pg.CONN) = struct dn_section_name_ht: (denom_hash, string) Hashtbl.t; } - let database_find_sk conn fname pub = + let sm_key_fname = Fpath.(Config.secrets_dir / "sm_key") + let sk_key_fname i = Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i) + + let dn_key_fname section_name = + Fpath.(Config.secrets_dir / Fmt.str "dn_%s" section_name) + + let database_find_sk conn pub = let* opt = Pg.find_signkey conn pub |> unwrap_err_caqti in match opt with | None -> - Fmt.error - "load_signkey error, no associated data found in database for \ - signkey `%s`." - (Fpath.to_string fname) + Fmt.error "secmod failure: a signkey could not be found in database" | Some sk_data -> Ok sk_data - let database_find_dn conn ~section_name h_pub = + let database_find_dn conn h_pub = let* opt = Pg.find_denom conn h_pub |> unwrap_err_caqti in match opt with | None -> Fmt.error - "load_denom error no associated metadata found in database for \ - denomination `%s`." - section_name + "secmod failure: a denomination could not be found in database" | Some dn_data -> Ok dn_data (* TODO clean up *) @@ -88,18 +90,10 @@ module Make (Conn : Pg.CONN) = struct let error_invalid_state = Fmt.error "secmod load error: invalid store state." in - let* sm_key = Data_file.read_eddsa Fpath.(Config.secrets_dir / "sk_sm") in + let* sm_key = Data_file.read_eddsa sm_key_fname in let* sk_keys = - let l = - List.init 1 (fun i -> Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i)) - in - let* l = - list_map - (fun fname -> - let+ opt = Data_file.read_eddsa fname in - Option.map (fun priv -> (fname, priv)) opt) - l - in + let l = List.init 1 sk_key_fname in + let* l = list_map (fun fname -> Data_file.read_eddsa fname) l in match opt_list l with Error () -> error_invalid_state | Ok opt -> Ok opt in let* dn_keys = @@ -108,8 +102,7 @@ module Make (Conn : Pg.CONN) = struct list_map (fun coin -> let section_name = coin.section_name in - let fname = Fpath.(Config.secrets_dir / section_name) in - let+ opt = Data_file.read_rsa fname in + let+ opt = Data_file.read_rsa (dn_key_fname section_name) in Option.map (fun priv -> (section_name, priv)) opt) all_coins in @@ -125,9 +118,9 @@ module Make (Conn : Pg.CONN) = struct (* sk *) let* l = list_map - (fun (fname, priv) -> + (fun priv -> let pub = EddsaPrivateKey.pub_of_priv priv in - let+ sk = database_find_sk conn fname pub in + let+ sk = database_find_sk conn pub in ((pub, sk), (pub, priv))) sk_keys in @@ -136,6 +129,7 @@ module Make (Conn : Pg.CONN) = struct (list_to_ht sk_l, list_to_ht priv_l) in (* dn *) + let dn_section_name_ht = Hashtbl.create 0xff in let* l = list_map (fun (section_name, priv) -> @@ -145,15 +139,18 @@ module Make (Conn : Pg.CONN) = struct |> RsaPublicKey.to_octets |> DenominationHash.hash in - let+ dn = database_find_dn conn ~section_name h_pub in + + (* fill dn_section_name_ht *) + Hashtbl.replace dn_section_name_ht h_pub section_name; + + let+ dn = database_find_dn conn h_pub in ((h_pub, dn), (h_pub, priv))) dn_keys in let dn_ht, dn_key_ht = - let dn_l, priv_l = List.split l in - (list_to_ht dn_l, list_to_ht priv_l) + match List.split l with l1, l2 -> (list_to_ht l1, list_to_ht l2) in - (* future keys are not stored (until they are signed) + (* future keys are not stored anywhere until they are certified with a master_sig so we don't have any future key to load *) let t = { @@ -167,7 +164,7 @@ module Make (Conn : Pg.CONN) = struct future_dn_ht= Hashtbl.create 0xff; future_sk_key_ht= Hashtbl.create 0xff; future_dn_key_ht= Hashtbl.create 0xff; - dn_section_name_ht= Hashtbl.create 0xff; + dn_section_name_ht; } in Ok (Some t) @@ -216,17 +213,16 @@ module Make (Conn : Pg.CONN) = struct age_restricted= _; } = assert (cipher = `RSA); - let open Time in - let start = Absolute.of_ptime (Ptime_clock.now ()) in + let start = Time.Absolute.of_ptime (Ptime_clock.now ()) in let stamp_start = Timestamp.of_absolute start in let stamp_expire_withdraw = - Timestamp.of_absolute @@ Absolute.add start duration_withdraw + Timestamp.of_absolute @@ Time.Absolute.add start duration_withdraw in let stamp_expire_deposit = - Timestamp.of_absolute @@ Absolute.add start duration_spend + Timestamp.of_absolute @@ Time.Absolute.add start duration_spend in let stamp_expire_legal = - Timestamp.of_absolute @@ Absolute.add start duration_legal + Timestamp.of_absolute @@ Time.Absolute.add start duration_legal in let priv, pub = RsaPrivateKey.generate ~bits:rsa_keysize () in let open Api in @@ -453,16 +449,11 @@ module Make (Conn : Pg.CONN) = struct Ok () let save () = - let* () = - let fname = Fpath.(Config.secrets_dir / "sk_sm") in - Data_file.write_eddsa fname t.sm_key - in + let* () = Data_file.write_eddsa sm_key_fname t.sm_key in let* () = Hashtbl.to_seq_values t.sk_key_ht |> List.of_seq - |> List.mapi (fun i priv -> - let fname = Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i) in - Data_file.write_eddsa fname priv) + |> List.mapi (fun i priv -> Data_file.write_eddsa (sk_key_fname i) priv) |> list_iter Fun.id in let* () = @@ -474,8 +465,7 @@ module Make (Conn : Pg.CONN) = struct | None -> Error "invalid state, section_name not found" | Some s -> Ok s in - let fname = Fpath.(Config.secrets_dir / section_name) in - Data_file.write_rsa fname priv) + Data_file.write_rsa (dn_key_fname section_name) priv) in Logs.info (fun m -> m "saved secmod private keys data"); Ok ()