diff --git a/src/api.ml b/src/api.ml index 74f40b79..4f294418 100644 --- a/src/api.ml +++ b/src/api.ml @@ -29,6 +29,8 @@ let encode_exn jsont v = Jsont_bytesrw.encode_string jsont v |> Result.get_ok let encode jsont v = Jsont_bytesrw.encode_string jsont v let decode jsont v = Jsont_bytesrw.decode_string jsont v +module DenominationHash = Bin_type.DenominationHash + module Account_operation = struct type t = | Withdraw @@ -70,26 +72,6 @@ module B32 = struct ~decode:B32.decode Caqti_type.string end -module HashCode : sig - type t - - val hash : string -> t - val of_b32 : B32.t -> (t, string) result - val to_denomination_hash : t -> Bin_type.DenominationHash.t - val jsont : t Jsont.t -end = struct - type t = B32.t - - let to_denomination_hash s = Bin_type.DenominationHash.of_octets s - - let hash s = - let open Digestif.SHA512 in - s |> digest_string |> to_raw_string - - let of_b32 = B32.decode - let jsont = B32.jsont -end - (* TODO error response - use GANA error codes https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/registry.rec *) @@ -442,7 +424,7 @@ end module DenomSignature = struct type t = { - h_denom_pub: HashCode.t; + h_denom_pub: DenominationHash.t; master_sig: DenominationKeyValidity.t; } @@ -451,7 +433,7 @@ module DenomSignature = struct let h_denom_pub v = v.h_denom_pub in let master_sig v = v.master_sig in map ~kind:"DenomSignature" make - |> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub + |> mem "h_denom_pub" DenominationHash.jsont ~enc:h_denom_pub |> mem "master_sig" DenominationKeyValidity.jsont ~enc:master_sig |> finish end @@ -883,7 +865,7 @@ end module AuditorDenominationKey = struct type t = { - denom_pub_h: HashCode.t; + denom_pub_h: DenominationHash.t; auditor_sig: ExchangeKeyValidity.t; } @@ -892,7 +874,7 @@ module AuditorDenominationKey = struct let denom_pub_h v = v.denom_pub_h in let auditor_sig v = v.auditor_sig in map ~kind:"AuditorDenominationKey" make - |> mem "denom_pub_h" HashCode.jsont ~enc:denom_pub_h + |> mem "denom_pub_h" DenominationHash.jsont ~enc:denom_pub_h |> mem "auditor_sig" ExchangeKeyValidity.jsont ~enc:auditor_sig |> finish end @@ -951,13 +933,13 @@ module SignKey = struct end module RecoupDenoms = struct - type t = { h_denom_pub: HashCode.t } + type t = { h_denom_pub: DenominationHash.t } let jsont = let make h_denom_pub = { h_denom_pub } in let h_denom_pub v = v.h_denom_pub in map ~kind:"RecoupDenoms" make - |> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub + |> mem "h_denom_pub" DenominationHash.jsont ~enc:h_denom_pub |> finish end diff --git a/src/bin_type.ml b/src/bin_type.ml index e2a82283..99a40dd0 100644 --- a/src/bin_type.ml +++ b/src/bin_type.ml @@ -97,17 +97,23 @@ module Hash_32 = struct | true -> Digestif.SHA256.of_raw_string s let to_octets = Digestif.SHA256.to_raw_string + let of_b32 s = Result.map of_octets (B32.decode s) let bin = let open Bin in map (bytes 32) of_octets to_octets + (* hashes are not b32 encoded in the database *) let caqti : t Caqti_type.t = let open Caqti_type in custom ~encode:(fun v -> Ok (to_octets v)) ~decode:(fun v -> Ok (of_octets v)) octets + + let jsont = + let enc v = B32.encode (to_octets v) in + Jsont.of_of_string ~kind:"Hash 32" of_b32 ~enc end module Hash_64 = struct @@ -126,16 +132,23 @@ module Hash_64 = struct | false -> Fmt.failwith "Hash.to_octets failure: data is not 64 bytes" | true -> s + let of_b32 s = Result.map of_octets (B32.decode s) + let bin = let open Bin in map (bytes 64) of_octets to_octets + (* hashes are not b32 encoded in the database *) let caqti : t Caqti_type.t = let open Caqti_type in custom ~encode:(fun v -> Ok (to_octets v)) ~decode:(fun v -> Ok (of_octets v)) octets + + let jsont = + let enc v = B32.encode (to_octets v) in + Jsont.of_of_string ~kind:"Hash 64" of_b32 ~enc end (* Hash over string + '\0' *) @@ -160,9 +173,11 @@ module type Hash_S = sig val bin : t Bin.t val caqti : t Caqti_type.t + val jsont : t Jsont.t val hash : string -> t val of_octets : string -> t val to_octets : t -> string + val of_b32 : B32.t -> (t, string) result end module FullPaytoHash : Hash_S = Hash_32 diff --git a/src/http_management.ml b/src/http_management.ml index 6df1d656..f24c88ff 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -117,9 +117,8 @@ end module Keys_post = struct let verify_denom_signature ~sm DenomSignature.{ h_denom_pub; master_sig } = - let denom_hash = HashCode.to_denomination_hash h_denom_pub in let* denom = - match Secmod.find_denom_data sm denom_hash with + match Secmod.find_denom_data sm h_denom_pub with | None -> Fmt.error "404 not found, One of the keys for which a signature was provided \ @@ -138,7 +137,7 @@ module Keys_post = struct fee_withdraw= denom.fee_withdraw; fee_deposit= denom.fee_deposit; fee_refresh= denom.fee_refresh; - denom_hash; + denom_hash= h_denom_pub; } in verify_f ~f:Secmod.verify_with_master_key master_sig r @@ -196,7 +195,6 @@ module Keys_post = struct let* () = denom_sigs |> List.map (fun DenomSignature.{ h_denom_pub; master_sig } -> - let h_denom_pub = HashCode.to_denomination_hash h_denom_pub in (h_denom_pub, master_sig)) |> Secmod.add_denom_master_signatures db_conn sm in @@ -238,8 +236,7 @@ module Denom_revoke = struct let db_conn = Vif.Server.device Devices.db_connection server in let sm = Vif.Server.device Devices.secmod server in let res = - let* h_denom_pub = HashCode.of_b32 h_denom_pub in - let h_denom_pub = HashCode.to_denomination_hash h_denom_pub in + let* h_denom_pub = DenominationHash.of_b32 h_denom_pub in let* v = Vif.Request.of_json req |> unwrap_err_msg in let* () = verify h_denom_pub v in let* () = do_ ~db_conn ~sm h_denom_pub v in diff --git a/src/pg.ml b/src/pg.ml index c57bc8e2..1a2dce80 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -9,7 +9,9 @@ GNU Taler db-events? it seems caqti/pgx does not support it - transaction *) + transaction + + should check validity of signatures got from db, for /management at least *) module type CONN = Caqti_miou.CONNECTION @@ -185,7 +187,7 @@ let insert_auditor_denom_sig = fun (module Conn : CONN) ~auditor_pub ~h_denom_pub ~auditor_sig -> Conn.exec insert_auditor_denom_sig (auditor_pub, h_denom_pub, auditor_sig) -let get_auditors = +let _get_auditors = let get_auditors = Caqti_type.(unit ->* t3 eddsa_pub string string) "SELECT auditor_pub, auditor_url, auditor_name FROM auditors WHERE \ @@ -193,7 +195,7 @@ let get_auditors = in fun (module Conn : CONN) () -> Conn.collect_list get_auditors () -let get_auditor_denoms = +let _get_auditor_denoms = let get_auditor_denoms = let auditor_sig = Bin_sig.ExchangeKeyValidity.caqti in Caqti_type.(unit ->* t3 eddsa_pub denomination_hash auditor_sig) @@ -204,6 +206,46 @@ let get_auditor_denoms = in fun (module Conn : CONN) () -> Conn.collect_list get_auditor_denoms () +(* TODO + maybe check that url and name are unique/same for each auditor_pub + do the ht logic out of pg.ml *) +let get_auditor_keys = + let get_auditor_keys = + let auditor_sig = Bin_sig.ExchangeKeyValidity.caqti in + Caqti_type.( + unit ->* t5 eddsa_pub string string denomination_hash auditor_sig) + "SELECT auditors.auditor_pub, auditors.url, auditors.name, \ + denominations.denom_pub_hash, auditor_denom_sigs.auditor_sig FROM \ + auditor_denom_sigs JOIN auditors USING (auditor_uuid) JOIN \ + denominations USING (denominations_serial) WHERE auditors.is_active" + in + fun (module Conn : CONN) () -> + let open Syntax in + let* l = Conn.collect_list get_auditor_keys () |> unwrap_err_caqti in + let ht = Hashtbl.create 0xff in + List.iter + (fun (pub, url, name, denom_pub_h, auditor_sig) -> + let k = (pub, url, name) in + match Hashtbl.find_opt ht k with + | None -> Hashtbl.replace ht k [ (denom_pub_h, auditor_sig) ] + | Some l -> Hashtbl.replace ht k ((denom_pub_h, auditor_sig) :: l)) + l; + let l = Hashtbl.to_seq ht |> List.of_seq in + let l = + List.map + (fun ((auditor_pub, auditor_url, auditor_name), auditor_denoms) -> + let denomination_keys = + List.map + (fun (denom_pub_h, auditor_sig) -> + AuditorDenominationKey.{ denom_pub_h; auditor_sig }) + auditor_denoms + in + AuditorKeys. + { auditor_pub; auditor_url; auditor_name; denomination_keys }) + l + in + Ok l + let insert_wire_fee = let insert_wire_fee = let master_sig = Bin_sig.MasterWireFee.caqti in diff --git a/src/pg_type.ml b/src/pg_type.ml index 4d14d19c..4a1ed95b 100644 --- a/src/pg_type.ml +++ b/src/pg_type.ml @@ -4,6 +4,9 @@ open Bin_type open Api open Caqti_type +(* TODO + check that we use Caqti_type.octets for binary data *) + let amount : Amount.t t = let open Amount in custom @@ -25,7 +28,7 @@ let eddsa_sig = EddsaSignature.caqti (* todo: enum type for wire_method? *) let wire_method = Caqti_type.string let payto_uri = Caqti_type.string -let b32 = Api.B32.caqti +let b32 = B32.caqti include struct (* alias for hash *) diff --git a/tools/offline_sig.ml b/tools/offline_sig.ml index 7c442251..eaeda431 100644 --- a/tools/offline_sig.ml +++ b/tools/offline_sig.ml @@ -19,11 +19,10 @@ let denom_signature ~master_key denom_secmod_sig= _; } = let octets = DenominationKey.to_octets denom_pub in - let h_denom_pub = HashCode.hash octets in + let h_denom_pub = DenominationHash.hash octets in let master_sig = let open Bin_sig.DenominationKeyValidity in let master = EddsaPrivateKey.(pub_of_priv master_key) in - let denom_hash = DenominationHash.hash octets in sign_f ~f:(EddsaSignature.sign ~key:master_key) { @@ -36,7 +35,7 @@ let denom_signature ~master_key fee_withdraw; fee_deposit; fee_refresh; - denom_hash; + denom_hash= h_denom_pub; } in DenomSignature.{ h_denom_pub; master_sig }