+ type for signature

This commit is contained in:
swrup 2025-12-03 16:19:11 +01:00
parent eb56150120
commit 577b2117a4
5 changed files with 217 additions and 201 deletions

View file

@ -6,6 +6,7 @@
- better types - better types
- issues with "never" = uint64_max *) - issues with "never" = uint64_max *)
open Crypto open Crypto
open Bin_signature
let encode_exn jsont v = Jsont_bytesrw.encode_string jsont v |> Result.get_ok 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 encode jsont v = Jsont_bytesrw.encode_string jsont v
@ -138,7 +139,7 @@ module FutureSignKey = struct
stamp_start: Timestamp.t; stamp_start: Timestamp.t;
stamp_expire: Timestamp.t; stamp_expire: Timestamp.t;
stamp_end: Timestamp.t; stamp_end: Timestamp.t;
signkey_secmod_sig: EddsaSignature.t; signkey_secmod_sig: SigningKeyAnnouncementPS.t;
} }
let jsont = let jsont =
@ -156,7 +157,8 @@ module FutureSignKey = struct
|> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start
|> mem "stamp_expire" Timestamp.jsont ~enc:stamp_expire |> mem "stamp_expire" Timestamp.jsont ~enc:stamp_expire
|> mem "stamp_end" Timestamp.jsont ~enc:stamp_end |> 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 |> finish
end end
@ -173,7 +175,7 @@ module FutureDenom = struct
fee_deposit: Amount.t; fee_deposit: Amount.t;
fee_refresh: Amount.t; fee_refresh: Amount.t;
fee_refund: Amount.t; fee_refund: Amount.t;
denom_secmod_sig: Bin_signature.DenominationKeyAnnouncementPS.Sig.t; denom_secmod_sig: DenominationKeyAnnouncementPS.t;
} }
let jsont = let jsont =
@ -220,8 +222,7 @@ module FutureDenom = struct
|> mem "fee_deposit" Amount.jsont ~enc:fee_deposit |> mem "fee_deposit" Amount.jsont ~enc:fee_deposit
|> mem "fee_refresh" Amount.jsont ~enc:fee_refresh |> mem "fee_refresh" Amount.jsont ~enc:fee_refresh
|> mem "fee_refund" Amount.jsont ~enc:fee_refund |> mem "fee_refund" Amount.jsont ~enc:fee_refund
|> mem "denom_secmod_sig" |> mem "denom_secmod_sig" DenominationKeyAnnouncementPS.jsont
Bin_signature.DenominationKeyAnnouncementPS.Sig.jsont
~enc:denom_secmod_sig ~enc:denom_secmod_sig
|> finish |> finish
end end
@ -268,7 +269,7 @@ end
module SignKeySignature = struct module SignKeySignature = struct
type t = { type t = {
key: EddsaPublicKey.t; key: EddsaPublicKey.t;
master_sig: EddsaSignature.t; master_sig: ExchangeSigningKeyValidityPS.t;
} }
let jsont = let jsont =
@ -278,14 +279,14 @@ module SignKeySignature = struct
let open Jsont.Object in let open Jsont.Object in
map ~kind:"SignKeySignature" make map ~kind:"SignKeySignature" make
|> mem "key" EddsaPublicKey.jsont ~enc:key |> mem "key" EddsaPublicKey.jsont ~enc:key
|> mem "master_sig" EddsaSignature.jsont ~enc:master_sig |> mem "master_sig" ExchangeSigningKeyValidityPS.jsont ~enc:master_sig
|> finish |> finish
end end
module DenomSignature = struct module DenomSignature = struct
type t = { type t = {
h_denom_pub: HashCode.t; h_denom_pub: HashCode.t;
master_sig: EddsaSignature.t; master_sig: DenominationKeyValidityPS.t;
} }
let jsont = let jsont =
@ -295,7 +296,7 @@ module DenomSignature = struct
let open Jsont.Object in let open Jsont.Object in
map ~kind:"DenomSignature" make map ~kind:"DenomSignature" make
|> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub |> 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 |> finish
end end

View file

@ -35,56 +35,31 @@ module Purpose = struct
let field purpose = Bin.field bin (fun _t -> purpose) let field purpose = Bin.field bin (fun _t -> purpose)
end end
module WithdrawRequestPS = struct module MK (R : sig
(* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) type r
type t = {
amount: Amount.t;
fee: Amount.t;
h_planchets: HashPlanchetsP.t;
blinding_seed: BlindingMasterSecret.t;
max_age_group: int32;
mask: AgeMask.t;
}
let bin = val bin : r Bin.t
let open Bin in end) : sig
Purpose.make_bin Taler_signatures.wallet_reserve_withdraw @@ fun purpose -> type r = R.r
record type t
(fun _purpose amount fee h_planchets blinding_seed max_age_group mask ->
{ amount; fee; h_planchets; blinding_seed; max_age_group; mask })
|+ Purpose.field purpose
|+ field Amount.bin (fun t -> t.amount)
|+ field Amount.bin (fun t -> t.fee)
|+ field HashPlanchetsP.bin (fun t -> t.h_planchets)
|+ field BlindingMasterSecret.bin (fun t -> t.blinding_seed)
|+ field beint32 (fun t -> t.max_age_group)
|+ field AgeMask.bin (fun t -> t.mask)
|> sealr
end
module WithdrawConfirmationPS = struct val sign : key:Crypto.EddsaPrivateKey.t -> r -> t
(* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW. val verify : key:Crypto.EddsaPublicKey.t -> t -> r -> bool
Signed by a `struct TALER_ExchangePrivateKeyP` using EdDSA. *) val jsont : t Jsont.t
type t = { end = struct
(* TODO TALER doc open Crypto
missing TALER_HashBlindedPlanchetsP*)
h_planchets: HashPlanchetsP.t;
noreveal_index: int32;
}
let bin = type r = R.r
let open Bin in type t = EddsaSignature.t
Purpose.make_bin Taler_signatures.exchange_confirm_withdraw
@@ fun purpose -> let bin = R.bin
record (fun _purpose h_planchets noreveal_index -> let sign ~key r = EddsaSignature.sign ~key (Bin.to_string bin r)
{ h_planchets; noreveal_index }) let verify ~key t r = EddsaSignature.verify ~key t ~msg:(Bin.to_string bin r)
|+ Purpose.field purpose let jsont = EddsaSignature.jsont
|+ field HashPlanchetsP.bin (fun t -> t.h_planchets)
|+ field beint32 (fun t -> t.noreveal_index)
|> sealr
end end
module DenominationKeyAnnouncementPS = struct module DenominationKeyAnnouncementPS = struct
module R = struct
(* TODO taler_signatures purpose (* TODO taler_signatures purpose
we use TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY instead here *) we use TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY instead here *)
(* purpose.purpose = TALER_SIGNATURE_SM_DENOMINATION_KEY *) (* purpose.purpose = TALER_SIGNATURE_SM_DENOMINATION_KEY *)
@ -97,9 +72,11 @@ module DenominationKeyAnnouncementPS = struct
let bin = let bin =
let open Bin in let open Bin in
Purpose.make_bin Taler_signatures.sm_rsa_denomination_key @@ fun purpose -> Purpose.make_bin Taler_signatures.sm_rsa_denomination_key
@@ fun purpose ->
record record
(fun _purpose h_denom_pub h_section_name anchor_time duration_withdraw -> (fun
_purpose h_denom_pub h_section_name anchor_time duration_withdraw ->
{ h_denom_pub; h_section_name; anchor_time; duration_withdraw }) { h_denom_pub; h_section_name; anchor_time; duration_withdraw })
|+ Purpose.field purpose |+ Purpose.field purpose
|+ field DenominationHash.bin (fun t -> t.h_denom_pub) |+ field DenominationHash.bin (fun t -> t.h_denom_pub)
@ -107,29 +84,16 @@ module DenominationKeyAnnouncementPS = struct
|+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time)
|+ field TimeRelativeNBO.bin (fun t -> t.duration_withdraw) |+ field TimeRelativeNBO.bin (fun t -> t.duration_withdraw)
|> sealr |> 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 end
module Sig : SIG = struct include R
type t = string include MK (R)
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 end
module SigningKeyAnnouncementPS = struct module SigningKeyAnnouncementPS = struct
module R = struct
(* purpose.purpose = TALER_SIGNATURE_SM_SIGNING_KEY *) (* purpose.purpose = TALER_SIGNATURE_SM_SIGNING_KEY *)
type t = { type r = {
exchange_pub: ExchangePublicKeyP.t; exchange_pub: ExchangePublicKeyP.t;
anchor_time: TimeAbsoluteNBO.t; anchor_time: TimeAbsoluteNBO.t;
duration: TimeRelativeNBO.t; duration: TimeRelativeNBO.t;
@ -145,11 +109,16 @@ module SigningKeyAnnouncementPS = struct
|+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time) |+ field TimeAbsoluteNBO.bin (fun t -> t.anchor_time)
|+ field TimeRelativeNBO.bin (fun t -> t.duration) |+ field TimeRelativeNBO.bin (fun t -> t.duration)
|> sealr |> sealr
end
include R
include MK (R)
end end
module DenominationKeyValidityPS = struct module DenominationKeyValidityPS = struct
module R = struct
(* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY *) (* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY *)
type t = { type r = {
master: MasterPublicKeyP.t; master: MasterPublicKeyP.t;
start: TimeAbsoluteNBO.t; start: TimeAbsoluteNBO.t;
expire_withdraw: TimeAbsoluteNBO.t; expire_withdraw: TimeAbsoluteNBO.t;
@ -204,11 +173,16 @@ module DenominationKeyValidityPS = struct
|+ field AmountNBO.bin (fun t -> t.fee_refresh) |+ field AmountNBO.bin (fun t -> t.fee_refresh)
|+ field DenominationHash.bin (fun t -> t.denom_hash) |+ field DenominationHash.bin (fun t -> t.denom_hash)
|> sealr |> sealr
end
include R
include MK (R)
end end
module ExchangeSigningKeyValidityPS = struct module ExchangeSigningKeyValidityPS = struct
module R = struct
(* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY *) (* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY *)
type t = { type r = {
start: TimeAbsoluteNBO.t; start: TimeAbsoluteNBO.t;
expire: TimeAbsoluteNBO.t; expire: TimeAbsoluteNBO.t;
end_: TimeAbsoluteNBO.t; (* "end" renamed to end_ *) end_: TimeAbsoluteNBO.t; (* "end" renamed to end_ *)
@ -227,10 +201,63 @@ module ExchangeSigningKeyValidityPS = struct
|+ field TimeAbsoluteNBO.bin (fun t -> t.end_) |+ field TimeAbsoluteNBO.bin (fun t -> t.end_)
|+ field ExchangePublicKeyP.bin (fun t -> t.signkey_pub) |+ field ExchangePublicKeyP.bin (fun t -> t.signkey_pub)
|> sealr |> sealr
end
include R
include MK (R)
end end
(* ### BIN IMPL END ### *) (* ### BIN IMPL END ### *)
module WithdrawRequestPS = struct
(* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *)
type t = {
amount: Amount.t;
fee: Amount.t;
h_planchets: HashPlanchetsP.t;
blinding_seed: BlindingMasterSecret.t;
max_age_group: int32;
mask: AgeMask.t;
}
let bin =
let open Bin in
Purpose.make_bin Taler_signatures.wallet_reserve_withdraw @@ fun purpose ->
record
(fun _purpose amount fee h_planchets blinding_seed max_age_group mask ->
{ amount; fee; h_planchets; blinding_seed; max_age_group; mask })
|+ Purpose.field purpose
|+ field Amount.bin (fun t -> t.amount)
|+ field Amount.bin (fun t -> t.fee)
|+ field HashPlanchetsP.bin (fun t -> t.h_planchets)
|+ field BlindingMasterSecret.bin (fun t -> t.blinding_seed)
|+ field beint32 (fun t -> t.max_age_group)
|+ field AgeMask.bin (fun t -> t.mask)
|> sealr
end
module WithdrawConfirmationPS = struct
(* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW.
Signed by a `struct TALER_ExchangePrivateKeyP` using EdDSA. *)
type t = {
(* TODO TALER doc
missing TALER_HashBlindedPlanchetsP*)
h_planchets: HashPlanchetsP.t;
noreveal_index: int32;
}
let bin =
let open Bin in
Purpose.make_bin Taler_signatures.exchange_confirm_withdraw
@@ fun purpose ->
record (fun _purpose h_planchets noreveal_index ->
{ h_planchets; noreveal_index })
|+ Purpose.field purpose
|+ field HashPlanchetsP.bin (fun t -> t.h_planchets)
|+ field beint32 (fun t -> t.noreveal_index)
|> sealr
end
module SingleWithdrawRequestPS = struct module SingleWithdrawRequestPS = struct
(* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *)
type t = { type t = {

View file

@ -51,8 +51,8 @@ end
module EddsaSignature : sig module EddsaSignature : sig
type t type t
val sign : key:Mirage_crypto_ec.Ed25519.priv -> string -> t val sign : key:EddsaPrivateKey.t -> string -> t
val sign_as_string : key:Mirage_crypto_ec.Ed25519.priv -> string -> string val verify : key:EddsaPublicKey.t -> t -> msg:string -> bool
val of_b32 : string -> (t, string) result val of_b32 : string -> (t, string) result
val to_b32 : t -> string val to_b32 : t -> string
val to_octets : 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 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: "The result is the concatenation of r and s, as specified in RFC 8032." *)
Mirage_crypto_ec.Ed25519.sign ~key s 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 sign_as_string ~key s = sign ~key s
let check_size t = let check_size t =
match String.length t = 64 with match String.length t = 64 with

View file

@ -1,7 +1,7 @@
open Api open Api
open Devices open Devices
let mk_future_denom denom_key_signf let mk_future_denom ~key
({ ({
pub; pub;
priv= _; priv= _;
@ -31,8 +31,7 @@ let mk_future_denom denom_key_signf
let duration_withdraw = let duration_withdraw =
Timestamp.diff stamp_start stamp_expire_withdraw |> Timestamp.of_span_exn Timestamp.diff stamp_start stamp_expire_withdraw |> Timestamp.of_span_exn
in in
Sig.sign denom_key_signf sign ~key { h_denom_pub; h_section_name; anchor_time; duration_withdraw }
{ h_denom_pub; h_section_name; anchor_time; duration_withdraw }
in in
FutureDenom. FutureDenom.
{ {
@ -50,7 +49,7 @@ let mk_future_denom denom_key_signf
denom_secmod_sig; denom_secmod_sig;
} }
let mk_future_signkey signkey_signf let mk_future_signkey ~key
({ pub; priv= _; stamp_start; stamp_expire; stamp_end; master_sig= _ } : ({ pub; priv= _; stamp_start; stamp_expire; stamp_end; master_sig= _ } :
Signkey.t) = Signkey.t) =
let signkey_secmod_sig = let signkey_secmod_sig =
@ -60,9 +59,7 @@ let mk_future_signkey signkey_signf
let duration = let duration =
Timestamp.diff stamp_start stamp_expire |> Timestamp.of_span_exn Timestamp.diff stamp_start stamp_expire |> Timestamp.of_span_exn
in in
{ exchange_pub; anchor_time; duration } sign ~key { exchange_pub; anchor_time; duration }
|> Bin.to_string bin
|> signkey_signf
in in
FutureSignKey. FutureSignKey.
{ key= pub; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig } { 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 secmod_denom.keys
|> List.filter (fun k -> Option.is_none k.Denomination.master_sig) |> List.filter (fun k -> Option.is_none k.Denomination.master_sig)
|> List.map (fun denom -> |> List.map (fun denom ->
let signf s = let key = secmod_denom.sm_key.Signkey.priv in
Crypto.EddsaSignature.sign_as_string mk_future_denom ~key denom)
~key:secmod_denom.sm_key.Signkey.priv s
in
mk_future_denom signf denom)
in in
let future_signkeys = let future_signkeys =
secmod_signkey.keys secmod_signkey.keys
|> List.filter (fun k -> Option.is_none k.Signkey.master_sig) |> List.filter (fun k -> Option.is_none k.Signkey.master_sig)
|> List.map (fun signkey -> |> List.map (fun signkey ->
let signf s = let key = secmod_denom.sm_key.Signkey.priv in
Crypto.EddsaSignature.sign ~key:secmod_denom.sm_key.Signkey.priv s mk_future_signkey ~key signkey)
in
mk_future_signkey signf signkey)
in in
let master_pub = Config.Exchange.master_public_key in let master_pub = Config.Exchange.master_public_key in
let denom_secmod_public_key = secmod_denom.sm_key.pub in let denom_secmod_public_key = secmod_denom.sm_key.pub in

View file

@ -25,6 +25,7 @@ let denom_signature ~master_key
let open Bin_signature.DenominationKeyValidityPS in let open Bin_signature.DenominationKeyValidityPS in
let master = EddsaPrivateKey.(pub_of_priv master_key) in let master = EddsaPrivateKey.(pub_of_priv master_key) in
let denom_hash = DenominationHash.hash octets in let denom_hash = DenominationHash.hash octets in
sign ~key:master_key
{ {
master; master;
start= stamp_start; start= stamp_start;
@ -37,8 +38,6 @@ let denom_signature ~master_key
fee_refresh; fee_refresh;
denom_hash; denom_hash;
} }
|> Bin.to_string bin
|> EddsaSignature.sign ~key:master_key
in in
DenomSignature.{ h_denom_pub; master_sig } DenomSignature.{ h_denom_pub; master_sig }
@ -54,14 +53,13 @@ let signkey_signature ~master_key
} = } =
let master_sig = let master_sig =
let open Bin_signature.ExchangeSigningKeyValidityPS in let open Bin_signature.ExchangeSigningKeyValidityPS in
sign ~key:master_key
{ {
start= stamp_start; start= stamp_start;
expire= stamp_expire; expire= stamp_expire;
end_= stamp_end; end_= stamp_end;
signkey_pub= key; signkey_pub= key;
} }
|> Bin.to_string bin
|> EddsaSignature.sign ~key:master_key
in in
SignKeySignature.{ key; master_sig } SignKeySignature.{ key; master_sig }