From 03ee804479c23c3a47779346c639005c2a2317e6 Mon Sep 17 00:00:00 2001 From: swrup Date: Wed, 18 Feb 2026 17:05:40 +0100 Subject: [PATCH] --- src/api.ml | 2 +- src/crypto.ml | 59 ++++++++++++++++++++++++++--------------------- src/signatures.ml | 33 +++++++++++++------------- 3 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/api.ml b/src/api.ml index 8a132db1..06a5f729 100644 --- a/src/api.ml +++ b/src/api.ml @@ -1253,7 +1253,7 @@ module ExchangeKeysResponse = struct (* Signature by the exchange master key of the SHA-256 hash of the normalized JSON-object of field extensions, if it was set. The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. *) - extensions_sig: EddsaSignature.t option; + extensions_sig: EddsaSignature_untyped.t option; } let jsont = diff --git a/src/crypto.ml b/src/crypto.ml index aac1d07d..0ee66fdb 100644 --- a/src/crypto.ml +++ b/src/crypto.ml @@ -143,53 +143,60 @@ module EddsaPrivateKey = struct end module EddsaSignature : sig - type t + type 'a t - val sign : key:EddsaPrivateKey.t -> string -> t + val sign : key:EddsaPrivateKey.t -> to_string:('a -> string) -> 'a -> 'a t (* Ok () on verification success *) - val verify : key:EddsaPublicKey.t -> t -> msg:string -> (unit, string) result - val to_octets : t -> string - val of_octets : string -> (t, string) result - val jsont : t Jsont.t - val bin : t Bin.t - val caqti : t Caqti_type.t + val verify : + key:EddsaPublicKey.t -> + to_string:('a -> string) -> + 'a -> + 'a t -> + (unit, string) result + + val to_octets : 'a t -> string + val of_octets : string -> ('a t, string) result + val jsont : 'a t Jsont.t + val bin : 'a t Bin.t + val caqti : 'a t Caqti_type.t end = struct (* transmitted as 64-bytes base32 binary-encoded objects with just the R and S values *) - type t = string + type 'a t = string - (* 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 + (* mirage_crypto: + "The result is the concatenation of r and s, as specified in RFC 8032." *) + let sign ~key ~to_string r = + let s = to_string r in + Mirage_crypto_ec.Ed25519.sign ~key s - let verify ~key s ~msg = - let b = Mirage_crypto_ec.Ed25519.verify ~key s ~msg in + let verify ~key ~to_string r t = + let msg = to_string r in + let b = Mirage_crypto_ec.Ed25519.verify ~key t ~msg in match b with - | false -> Error "signature verification failure: invalid signature" + | false -> Error "EddsaSignature verification: invalid signature" | true -> Ok () let to_octets t = t + let check_len t = + match String.length t = 64 with + | false -> Error "EddsaSignature: invalid string length" + | true -> Ok () + let of_octets v = - match String.length v = 64 with - | false -> - Fmt.error "EddsaSignature.of_octets failure: data is not 64 bytes." - | true -> Ok v + let+ () = check_len v in + v let bin = let of_octets_exn t = of_octets t |> Result.get_ok in Bin.map (Bin.bytes 64) of_octets_exn to_octets - let check_size t = - match String.length t = 64 with - | false -> Error "EddsaSignature: invalid string length" - | true -> Ok () - let jsont = let of_b32 s = let* t = B32.decode s in - let+ () = check_size t in - t + of_octets t in let to_b32 = B32.encode in Jsont.of_of_string ~kind:"EddsaSignature" of_b32 ~enc:to_b32 @@ -265,7 +272,7 @@ end (* some type aliases, just for prettier .mli *) type eddsa_priv = EddsaPrivateKey.t type eddsa_pub = EddsaPublicKey.t -type eddsa_sig = EddsaSignature.t +type 'a eddsa_sig = 'a EddsaSignature.t type rsa_priv = RsaPrivateKey.t type rsa_pub = RsaPublicKey.t type rsa_sig = RsaSignature.t diff --git a/src/signatures.ml b/src/signatures.ml index 80cebad6..94db59eb 100644 --- a/src/signatures.ml +++ b/src/signatures.ml @@ -6,6 +6,12 @@ better handling of decoding failure *) open Hash +module EddsaSignature_untyped = struct + include Crypto.EddsaSignature + + type nonrec t = string t +end + module Aliases = struct module Timestamp = struct type t = Time.Timestamp.t @@ -58,10 +64,10 @@ module Aliases = struct module ExchangePrivateKeyP = EddsaPrivateKey module MasterPrivateKeyP = EddsaPrivateKey module CoinSpendPrivateKeyP = EddsaPrivateKey - module MasterSignatureP = EddsaSignature - module ReserveSignatureP = EddsaSignature - module ExchangeSignatureP = EddsaSignature - module CoinSpendSignatureP = EddsaSignature + module MasterSignatureP = EddsaSignature_untyped + module ReserveSignatureP = EddsaSignature_untyped + module ExchangeSignatureP = EddsaSignature_untyped + module CoinSpendSignatureP = EddsaSignature_untyped end open Aliases @@ -157,30 +163,23 @@ end) : sig type r = R.r type t - val sign_f : f:(string -> eddsa_sig) -> r -> t - - val verify_f : - f:(eddsa_sig -> msg:string -> (unit, string) result) -> - t -> - r -> - (unit, string) result - + val sign : key:EddsaPrivateKey.t -> r -> t val jsont : t Jsont.t val caqti : t Caqti_type.t - (* TODO rm *) + (* TODO rm? *) (* escape hatch, only needed for /keys `exchange_sig` (signature over contatentation of all of the master_sigs) *) val to_octets : t -> string end = struct open Crypto type r = R.r - type t = EddsaSignature.t + type t = r EddsaSignature.t - let sign_f ~f r = f (Bin.to_string R.bin r) - let verify_f ~f t r = f t ~msg:(Bin.to_string R.bin r) + let to_string : r -> string = Bin.to_string R.bin + let sign ~key r = EddsaSignature.sign ~key ~to_string r let jsont = EddsaSignature.jsont - let caqti : EddsaSignature.t Caqti_type.t = EddsaSignature.caqti + let caqti = EddsaSignature.caqti let to_octets t = EddsaSignature.to_octets t end