module Config_types = struct module Currency = struct type t = { enabled: [ `YES | `NO ]; code: string; name: string; fractional_input_digits: int; fractional_normal_digits: int; fractional_trailing_zero_digits: int; alt_unit_names: (int * string) list; } end module Coin = struct type t = { (* section_name: Name in the configuration file that defines this denomination *) section_name: string; value: Amount.t; duration_withdraw: Ptime.Span.t; duration_spend: Ptime.Span.t; duration_legal: Ptime.Span.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; cipher: [ (* `CS |*) `RSA ]; rsa_keysize: int; (* : int option (only if `RSA) *) age_restricted: [ (*`YES|*) `NO ]; } end end module HashCode = struct type t = string end (* https://docs.taler.net/core/api-common.html#tsref-type-ErrorDetail *) module ErrorDetail = struct (* TODO GANA error codes https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/registry.rec *) type t = { code: int; hint: string option; } end (* TODO number - number is "float", but we probably want int everywhere instead - numeric values capped at 2^53 -1 inclusive because json *) (* TODO time - int64 instead of float/int (binary format time in int64 us) ? make api types take in Ptime.t instead of Timestamp.t ? issues with "never" = uint64_max *) module Timestamp = struct type t = | Seconds of float | Never let of_ptime p = Seconds (Ptime.to_float_s p) end module RelativeTime = struct type t = | Microseconds of float | Forever end module Amount = struct include Amount let jsont = Jsont.of_of_string ~kind:"Amount" of_string ~enc:to_string end (* TODO key format - check what is the exact format in GNUNET - endianess issue? *) module EddsaPublicKey = struct (* EdDSA and ECDHE public keys always point on Curve25519 and represented using the standard 256 bits Ed25519 compact format, converted to Crockford Base32. *) type t = Mirage_crypto_ec.Ed25519.pub let to_octets t = Mirage_crypto_ec.Ed25519.pub_to_octets t let of_octets t = Mirage_crypto_ec.Ed25519.pub_of_octets t let of_b32 s = let open Syntax in let open Mirage_crypto_ec in let* octets = B32.decode s in match Ed25519.pub_of_octets octets with | Error e -> Fmt.error "%a" pp_error e | Ok pub -> Ok pub let to_b32 t = B32.encode (to_octets t) let jsont = Jsont.of_of_string ~kind:"EddsaPublicKey" of_b32 ~enc:to_b32 end module EddsaSignature : sig type t val to_octets : t -> string val sign : key:Mirage_crypto_ec.Ed25519.priv -> string -> t val of_b32 : string -> (t, string) result val to_b32 : t -> string val jsont : t Jsont.t end = struct (* EdDSA signatures are transmitted as 64-bytes base32 binary-encoded objects with just the R and S values (base32_ binary-only). They are signature over a c-struct like `TALER_xxxPS` + with a purpose *) type t = string let to_octets t = t (* TODO key format is it exactly like in GNU_CRYPTO? endianess issue? *) 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 of_b32 s = B32.decode s let to_b32 t = let s = B32.encode t in assert (String.length s = 64); s let jsont = Jsont.of_of_string ~kind:"EddsaSignature" of_b32 ~enc:to_b32 end module RsaPublicKey = struct open Binary_formats.RsaPublicKey type t = Mirage_crypto_pk.Rsa.pub let of_b32 s = let open Syntax in let open Binary_formats.RsaPublicKey in let* s = B32.decode s in let* v = of_octets s in let+ v = Mirage_crypto_pk.Rsa.pub ~n:v.n ~e:v.e |> unwrap_err_msg in v let to_b32 t = B32.encode (to_octets t) let jsont = Jsont.of_of_string ~kind:"RsaPublicKey" of_b32 ~enc:to_b32 end module RsaSignature : sig type t val to_octets : t -> string val sign : key:Mirage_crypto_pk.Rsa.priv -> string -> t val of_b32 : string -> (t, string) result val to_b32 : t -> string val jsont : t Jsont.t end = struct type t = string let to_octets t = t (* no Rsa.sign(?): decrypt is equivalent to sign *) let sign ~key s = Mirage_crypto_pk.Rsa.decrypt ~crt_hardening:true ~mask:`Yes ~key s let of_b32 s = B32.decode s let to_b32 t = B32.encode t let jsont = Jsont.of_of_string ~kind:"RsaSignature" of_b32 ~enc:to_b32 end module RsaDenominationKey = struct type t = { age_mask: int; rsa_pub: RsaPublicKey.t; } end (* not implemented *) module CSDenominationKey = struct (* Clause Schnorr *) type t = { age_mask: int; cs_pub: string; } end module DenominationKey = struct type t = | Rsa of RsaDenominationKey.t | CS of CSDenominationKey.t end module FutureSignKey = struct type t = { (* The actual exchange's EdDSA signing public key *) key: EddsaPublicKey.t; (* Initial validity date for the signing key. *) stamp_start: Timestamp.t; (* Date when the exchange will stop using the signing key, allowed to overlap slightly with the next signing key's validity to allow for clock skew. *) stamp_expire: Timestamp.t; (* Date when all signatures made by the signing key expire and should henceforth no longer be considered valid in legal disputes. *) stamp_end: Timestamp.t; (* Signature over TALER_SigningKeyAnnouncementPS for this signing key by the signkey security module using purpose TALER_SIGNATURE_SM_SIGNING_KEY. *) signkey_secmod_sig: EddsaSignature.t; } end module FutureDenom = struct type t = { section_name: string; value: Amount.t; stamp_start: Timestamp.t; stamp_expire_withdraw: Timestamp.t; stamp_expire_deposit: Timestamp.t; stamp_expire_legal: Timestamp.t; denom_pub: DenominationKey.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; (* Signature by the denomination security module over TALER_DenominationKeyAnnouncementPS for this denomination with purpose TALER_SIGNATURE_SM_DENOMINATION_KEY. *) denom_secmod_sig: EddsaSignature.t; } end module FutureKeysResponse = struct type t = { future_denoms: FutureDenom.t list; future_signkeys: FutureSignKey.t list; master_pub: EddsaPublicKey.t; denom_secmod_public_key: EddsaPublicKey.t; signkey_secmod_public_key: EddsaPublicKey.t; } end