From 577b2117a4cefe37a2e10b5ef77131945eb926a0 Mon Sep 17 00:00:00 2001 From: swrup Date: Wed, 3 Dec 2025 16:19:11 +0100 Subject: [PATCH] + type for signature --- src/api.ml | 19 +-- src/bin_signature.ml | 321 +++++++++++++++++++++++-------------------- src/crypto.ml | 12 +- src/management.ml | 24 ++-- tools/offline_bin.ml | 42 +++--- 5 files changed, 217 insertions(+), 201 deletions(-) diff --git a/src/api.ml b/src/api.ml index 47d2156e..96118999 100644 --- a/src/api.ml +++ b/src/api.ml @@ -6,6 +6,7 @@ - better types - issues with "never" = uint64_max *) open Crypto +open Bin_signature let encode_exn jsont v = Jsont_bytesrw.encode_string jsont v |> Result.get_ok let encode jsont v = Jsont_bytesrw.encode_string jsont v @@ -138,7 +139,7 @@ module FutureSignKey = struct stamp_start: Timestamp.t; stamp_expire: Timestamp.t; stamp_end: Timestamp.t; - signkey_secmod_sig: EddsaSignature.t; + signkey_secmod_sig: SigningKeyAnnouncementPS.t; } let jsont = @@ -156,7 +157,8 @@ module FutureSignKey = struct |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_expire" Timestamp.jsont ~enc:stamp_expire |> mem "stamp_end" Timestamp.jsont ~enc:stamp_end - |> mem "signkey_secmod_sig" EddsaSignature.jsont ~enc:signkey_secmod_sig + |> mem "signkey_secmod_sig" SigningKeyAnnouncementPS.jsont + ~enc:signkey_secmod_sig |> finish end @@ -173,7 +175,7 @@ module FutureDenom = struct fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; - denom_secmod_sig: Bin_signature.DenominationKeyAnnouncementPS.Sig.t; + denom_secmod_sig: DenominationKeyAnnouncementPS.t; } let jsont = @@ -220,8 +222,7 @@ module FutureDenom = struct |> mem "fee_deposit" Amount.jsont ~enc:fee_deposit |> mem "fee_refresh" Amount.jsont ~enc:fee_refresh |> mem "fee_refund" Amount.jsont ~enc:fee_refund - |> mem "denom_secmod_sig" - Bin_signature.DenominationKeyAnnouncementPS.Sig.jsont + |> mem "denom_secmod_sig" DenominationKeyAnnouncementPS.jsont ~enc:denom_secmod_sig |> finish end @@ -268,7 +269,7 @@ end module SignKeySignature = struct type t = { key: EddsaPublicKey.t; - master_sig: EddsaSignature.t; + master_sig: ExchangeSigningKeyValidityPS.t; } let jsont = @@ -278,14 +279,14 @@ module SignKeySignature = struct let open Jsont.Object in map ~kind:"SignKeySignature" make |> mem "key" EddsaPublicKey.jsont ~enc:key - |> mem "master_sig" EddsaSignature.jsont ~enc:master_sig + |> mem "master_sig" ExchangeSigningKeyValidityPS.jsont ~enc:master_sig |> finish end module DenomSignature = struct type t = { h_denom_pub: HashCode.t; - master_sig: EddsaSignature.t; + master_sig: DenominationKeyValidityPS.t; } let jsont = @@ -295,7 +296,7 @@ module DenomSignature = struct let open Jsont.Object in map ~kind:"DenomSignature" make |> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub - |> mem "master_sig" EddsaSignature.jsont ~enc:master_sig + |> mem "master_sig" DenominationKeyValidityPS.jsont ~enc:master_sig |> finish end diff --git a/src/bin_signature.ml b/src/bin_signature.ml index f7d30051..e6b3690a 100644 --- a/src/bin_signature.ml +++ b/src/bin_signature.ml @@ -35,6 +35,180 @@ module Purpose = struct let field purpose = Bin.field bin (fun _t -> purpose) end +module MK (R : sig + type r + + val bin : r Bin.t +end) : sig + type r = R.r + type t + + val sign : key:Crypto.EddsaPrivateKey.t -> r -> t + val verify : key:Crypto.EddsaPublicKey.t -> t -> r -> bool + val jsont : t Jsont.t +end = struct + open Crypto + + type r = R.r + type t = EddsaSignature.t + + let bin = R.bin + let sign ~key r = EddsaSignature.sign ~key (Bin.to_string bin r) + let verify ~key t r = EddsaSignature.verify ~key t ~msg:(Bin.to_string bin r) + let jsont = EddsaSignature.jsont +end + +module DenominationKeyAnnouncementPS = struct + module R = struct + (* TODO taler_signatures purpose + we use TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY instead here *) + (* purpose.purpose = TALER_SIGNATURE_SM_DENOMINATION_KEY *) + type r = { + h_denom_pub: DenominationHash.t; + h_section_name: Hash_64_cstr.t; + anchor_time: TimeAbsoluteNBO.t; + duration_withdraw: TimeRelativeNBO.t; + } + + let bin = + let open Bin in + Purpose.make_bin Taler_signatures.sm_rsa_denomination_key + @@ fun purpose -> + record + (fun + _purpose h_denom_pub h_section_name anchor_time duration_withdraw -> + { h_denom_pub; h_section_name; anchor_time; duration_withdraw }) + |+ Purpose.field purpose + |+ field DenominationHash.bin (fun t -> t.h_denom_pub) + |+ field Hash_64_cstr.bin (fun t -> t.h_section_name) + |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) + |+ field TimeRelativeNBO.bin (fun t -> t.duration_withdraw) + |> sealr + end + + include R + include MK (R) +end + +module SigningKeyAnnouncementPS = struct + module R = struct + (* purpose.purpose = TALER_SIGNATURE_SM_SIGNING_KEY *) + type r = { + exchange_pub: ExchangePublicKeyP.t; + anchor_time: TimeAbsoluteNBO.t; + duration: TimeRelativeNBO.t; + } + + let bin = + let open Bin in + Purpose.make_bin Taler_signatures.sm_signing_key @@ fun purpose -> + record (fun _purpose exchange_pub anchor_time duration -> + { exchange_pub; anchor_time; duration }) + |+ Purpose.field purpose + |+ field ExchangePublicKeyP.bin (fun t -> t.exchange_pub) + |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) + |+ field TimeRelativeNBO.bin (fun t -> t.duration) + |> sealr + end + + include R + include MK (R) +end + +module DenominationKeyValidityPS = struct + module R = struct + (* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY *) + type r = { + master: MasterPublicKeyP.t; + start: TimeAbsoluteNBO.t; + expire_withdraw: TimeAbsoluteNBO.t; + expire_spend: TimeAbsoluteNBO.t; + expire_legal: TimeAbsoluteNBO.t; + value: AmountNBO.t; + fee_withdraw: AmountNBO.t; + fee_deposit: AmountNBO.t; + fee_refresh: AmountNBO.t; + denom_hash: DenominationHash.t; + } + + let bin = + let open Bin in + Purpose.make_bin Taler_signatures.master_denomination_key_validity + @@ fun purpose -> + record + (fun + _purpose + master + start + expire_withdraw + expire_spend + expire_legal + value + fee_withdraw + fee_deposit + fee_refresh + denom_hash + -> + { + master; + start; + expire_withdraw; + expire_spend; + expire_legal; + value; + fee_withdraw; + fee_deposit; + fee_refresh; + denom_hash; + }) + |+ Purpose.field purpose + |+ field MasterPublicKeyP.bin (fun t -> t.master) + |+ field TimeAbsoluteNBO.bin (fun t -> t.start) + |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_withdraw) + |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_spend) + |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_legal) + |+ field AmountNBO.bin (fun t -> t.value) + |+ field AmountNBO.bin (fun t -> t.fee_withdraw) + |+ field AmountNBO.bin (fun t -> t.fee_deposit) + |+ field AmountNBO.bin (fun t -> t.fee_refresh) + |+ field DenominationHash.bin (fun t -> t.denom_hash) + |> sealr + end + + include R + include MK (R) +end + +module ExchangeSigningKeyValidityPS = struct + module R = struct + (* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY *) + type r = { + start: TimeAbsoluteNBO.t; + expire: TimeAbsoluteNBO.t; + end_: TimeAbsoluteNBO.t; (* "end" renamed to end_ *) + signkey_pub: ExchangePublicKeyP.t; + } + + let bin = + let open Bin in + Purpose.make_bin Taler_signatures.master_signing_key_validity + @@ fun purpose -> + record (fun _purpose start expire end_ signkey_pub -> + { start; expire; end_; signkey_pub }) + |+ Purpose.field purpose + |+ field TimeAbsoluteNBO.bin (fun t -> t.start) + |+ field TimeAbsoluteNBO.bin (fun t -> t.expire) + |+ field TimeAbsoluteNBO.bin (fun t -> t.end_) + |+ field ExchangePublicKeyP.bin (fun t -> t.signkey_pub) + |> sealr + end + + include R + include MK (R) +end + +(* ### BIN IMPL END ### *) + module WithdrawRequestPS = struct (* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) type t = { @@ -84,153 +258,6 @@ module WithdrawConfirmationPS = struct |> sealr end -module DenominationKeyAnnouncementPS = struct - (* TODO taler_signatures purpose - we use TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY instead here *) - (* purpose.purpose = TALER_SIGNATURE_SM_DENOMINATION_KEY *) - type r = { - h_denom_pub: DenominationHash.t; - h_section_name: Hash_64_cstr.t; - anchor_time: TimeAbsoluteNBO.t; - duration_withdraw: TimeRelativeNBO.t; - } - - let bin = - let open Bin in - Purpose.make_bin Taler_signatures.sm_rsa_denomination_key @@ fun purpose -> - record - (fun _purpose h_denom_pub h_section_name anchor_time duration_withdraw -> - { h_denom_pub; h_section_name; anchor_time; duration_withdraw }) - |+ Purpose.field purpose - |+ field DenominationHash.bin (fun t -> t.h_denom_pub) - |+ field Hash_64_cstr.bin (fun t -> t.h_section_name) - |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) - |+ field TimeRelativeNBO.bin (fun t -> t.duration_withdraw) - |> sealr - - module type SIG = sig - type t - - val sign : (string -> string) -> r -> t - val verify : (string -> msg:string -> bool) -> t -> r -> bool - val jsont : t Jsont.t - end - - module Sig : SIG = struct - type t = string - - let sign f r = f @@ Bin.to_string bin r - let verify f s r = f s ~msg:(Bin.to_string bin r) - - (* TODO B32.jsont, for others types too *) - let jsont = Jsont.string - end -end - -module SigningKeyAnnouncementPS = struct - (* purpose.purpose = TALER_SIGNATURE_SM_SIGNING_KEY *) - type t = { - exchange_pub: ExchangePublicKeyP.t; - anchor_time: TimeAbsoluteNBO.t; - duration: TimeRelativeNBO.t; - } - - let bin = - let open Bin in - Purpose.make_bin Taler_signatures.sm_signing_key @@ fun purpose -> - record (fun _purpose exchange_pub anchor_time duration -> - { exchange_pub; anchor_time; duration }) - |+ Purpose.field purpose - |+ field ExchangePublicKeyP.bin (fun t -> t.exchange_pub) - |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) - |+ field TimeRelativeNBO.bin (fun t -> t.duration) - |> sealr -end - -module DenominationKeyValidityPS = struct - (* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY *) - type t = { - master: MasterPublicKeyP.t; - start: TimeAbsoluteNBO.t; - expire_withdraw: TimeAbsoluteNBO.t; - expire_spend: TimeAbsoluteNBO.t; - expire_legal: TimeAbsoluteNBO.t; - value: AmountNBO.t; - fee_withdraw: AmountNBO.t; - fee_deposit: AmountNBO.t; - fee_refresh: AmountNBO.t; - denom_hash: DenominationHash.t; - } - - let bin = - let open Bin in - Purpose.make_bin Taler_signatures.master_denomination_key_validity - @@ fun purpose -> - record - (fun - _purpose - master - start - expire_withdraw - expire_spend - expire_legal - value - fee_withdraw - fee_deposit - fee_refresh - denom_hash - -> - { - master; - start; - expire_withdraw; - expire_spend; - expire_legal; - value; - fee_withdraw; - fee_deposit; - fee_refresh; - denom_hash; - }) - |+ Purpose.field purpose - |+ field MasterPublicKeyP.bin (fun t -> t.master) - |+ field TimeAbsoluteNBO.bin (fun t -> t.start) - |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_withdraw) - |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_spend) - |+ field TimeAbsoluteNBO.bin (fun t -> t.expire_legal) - |+ field AmountNBO.bin (fun t -> t.value) - |+ field AmountNBO.bin (fun t -> t.fee_withdraw) - |+ field AmountNBO.bin (fun t -> t.fee_deposit) - |+ field AmountNBO.bin (fun t -> t.fee_refresh) - |+ field DenominationHash.bin (fun t -> t.denom_hash) - |> sealr -end - -module ExchangeSigningKeyValidityPS = struct - (* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY *) - type t = { - start: TimeAbsoluteNBO.t; - expire: TimeAbsoluteNBO.t; - end_: TimeAbsoluteNBO.t; (* "end" renamed to end_ *) - signkey_pub: ExchangePublicKeyP.t; - } - - let bin = - let open Bin in - Purpose.make_bin Taler_signatures.master_signing_key_validity - @@ fun purpose -> - record (fun _purpose start expire end_ signkey_pub -> - { start; expire; end_; signkey_pub }) - |+ Purpose.field purpose - |+ field TimeAbsoluteNBO.bin (fun t -> t.start) - |+ field TimeAbsoluteNBO.bin (fun t -> t.expire) - |+ field TimeAbsoluteNBO.bin (fun t -> t.end_) - |+ field ExchangePublicKeyP.bin (fun t -> t.signkey_pub) - |> sealr -end - -(* ### BIN IMPL END ### *) - module SingleWithdrawRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) type t = { diff --git a/src/crypto.ml b/src/crypto.ml index 8fda65f3..2c5ae619 100644 --- a/src/crypto.ml +++ b/src/crypto.ml @@ -51,8 +51,8 @@ end module EddsaSignature : sig type t - val sign : key:Mirage_crypto_ec.Ed25519.priv -> string -> t - val sign_as_string : key:Mirage_crypto_ec.Ed25519.priv -> string -> string + val sign : key:EddsaPrivateKey.t -> string -> t + val verify : key:EddsaPublicKey.t -> t -> msg:string -> bool val of_b32 : string -> (t, string) result val to_b32 : t -> string val to_octets : t -> string @@ -78,11 +78,9 @@ end = struct let bin = Bin.map (Bin.bytes 64) of_octets to_octets - let sign ~key s = - (* mirage_crypto: "The result is the concatenation of r and s, as specified in RFC 8032." *) - Mirage_crypto_ec.Ed25519.sign ~key s - - let sign_as_string ~key s = sign ~key s + (* mirage_crypto: "The result is the concatenation of r and s, as specified in RFC 8032." *) + let sign ~key s = Mirage_crypto_ec.Ed25519.sign ~key s + let verify ~key s ~msg = Mirage_crypto_ec.Ed25519.verify ~key s ~msg let check_size t = match String.length t = 64 with diff --git a/src/management.ml b/src/management.ml index 1aff93fe..1b443fdc 100644 --- a/src/management.ml +++ b/src/management.ml @@ -1,7 +1,7 @@ open Api open Devices -let mk_future_denom denom_key_signf +let mk_future_denom ~key ({ pub; priv= _; @@ -31,8 +31,7 @@ let mk_future_denom denom_key_signf let duration_withdraw = Timestamp.diff stamp_start stamp_expire_withdraw |> Timestamp.of_span_exn in - Sig.sign denom_key_signf - { h_denom_pub; h_section_name; anchor_time; duration_withdraw } + sign ~key { h_denom_pub; h_section_name; anchor_time; duration_withdraw } in FutureDenom. { @@ -50,7 +49,7 @@ let mk_future_denom denom_key_signf denom_secmod_sig; } -let mk_future_signkey signkey_signf +let mk_future_signkey ~key ({ pub; priv= _; stamp_start; stamp_expire; stamp_end; master_sig= _ } : Signkey.t) = let signkey_secmod_sig = @@ -60,9 +59,7 @@ let mk_future_signkey signkey_signf let duration = Timestamp.diff stamp_start stamp_expire |> Timestamp.of_span_exn in - { exchange_pub; anchor_time; duration } - |> Bin.to_string bin - |> signkey_signf + sign ~key { exchange_pub; anchor_time; duration } in FutureSignKey. { key= pub; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig } @@ -73,20 +70,15 @@ let mk_future_keys_response (secmod_signkey : Secmod_signkey.t) secmod_denom.keys |> List.filter (fun k -> Option.is_none k.Denomination.master_sig) |> List.map (fun denom -> - let signf s = - Crypto.EddsaSignature.sign_as_string - ~key:secmod_denom.sm_key.Signkey.priv s - in - mk_future_denom signf denom) + let key = secmod_denom.sm_key.Signkey.priv in + mk_future_denom ~key denom) in let future_signkeys = secmod_signkey.keys |> List.filter (fun k -> Option.is_none k.Signkey.master_sig) |> List.map (fun signkey -> - let signf s = - Crypto.EddsaSignature.sign ~key:secmod_denom.sm_key.Signkey.priv s - in - mk_future_signkey signf signkey) + let key = secmod_denom.sm_key.Signkey.priv in + mk_future_signkey ~key signkey) in let master_pub = Config.Exchange.master_public_key in let denom_secmod_public_key = secmod_denom.sm_key.pub in diff --git a/tools/offline_bin.ml b/tools/offline_bin.ml index 1919706d..469fc03d 100644 --- a/tools/offline_bin.ml +++ b/tools/offline_bin.ml @@ -25,20 +25,19 @@ let denom_signature ~master_key let open Bin_signature.DenominationKeyValidityPS in let master = EddsaPrivateKey.(pub_of_priv master_key) in let denom_hash = DenominationHash.hash octets in - { - master; - 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; - denom_hash; - } - |> Bin.to_string bin - |> EddsaSignature.sign ~key:master_key + sign ~key:master_key + { + master; + 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; + denom_hash; + } in DenomSignature.{ h_denom_pub; master_sig } @@ -54,14 +53,13 @@ let signkey_signature ~master_key } = let master_sig = let open Bin_signature.ExchangeSigningKeyValidityPS in - { - start= stamp_start; - expire= stamp_expire; - end_= stamp_end; - signkey_pub= key; - } - |> Bin.to_string bin - |> EddsaSignature.sign ~key:master_key + sign ~key:master_key + { + start= stamp_start; + expire= stamp_expire; + end_= stamp_end; + signkey_pub= key; + } in SignKeySignature.{ key; master_sig }