This commit is contained in:
parent
f3de6ea80d
commit
32966487da
7 changed files with 136 additions and 68 deletions
1
data/eddsa_master_offline
Normal file
1
data/eddsa_master_offline
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
mÔŻ9Wŕü]w×LčyŰ ăď[şşş¶ \ă<>ŠUg(
|
||||||
|
|
@ -88,3 +88,24 @@ let of_string =
|
||||||
(char '.' *> parse_int32)
|
(char '.' *> parse_int32)
|
||||||
in
|
in
|
||||||
fun s -> parse_string ~consume:Consume.All parse_t s |> Result.join
|
fun s -> parse_string ~consume:Consume.All parse_t s |> Result.join
|
||||||
|
|
||||||
|
let jsont = Jsont.of_of_string ~kind:"Amount" of_string ~enc:to_string
|
||||||
|
let currency_len = 12
|
||||||
|
|
||||||
|
let bin =
|
||||||
|
let open Bin in
|
||||||
|
record (fun _value _fraction _currency ->
|
||||||
|
(* no need to decode amount? *)
|
||||||
|
assert false)
|
||||||
|
|+ field neint64 (fun t -> t.value)
|
||||||
|
|+ field neint32 (fun t -> t.fraction)
|
||||||
|
|+ field (bytes currency_len) (fun t -> t.currency)
|
||||||
|
|> sealr
|
||||||
|
|
||||||
|
let bin_nbo =
|
||||||
|
let open Bin in
|
||||||
|
record (fun _value _fraction _currency -> assert false)
|
||||||
|
|+ field beint64 (fun t -> t.value)
|
||||||
|
|+ field beint32 (fun t -> t.fraction)
|
||||||
|
|+ field (bytes currency_len) (fun t -> t.currency)
|
||||||
|
|> sealr
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,9 @@ val make :
|
||||||
val pp : Format.formatter -> t -> unit
|
val pp : Format.formatter -> t -> unit
|
||||||
val to_string : t -> string
|
val to_string : t -> string
|
||||||
val of_string : string -> (t, string) result
|
val of_string : string -> (t, string) result
|
||||||
|
val currency_len : int
|
||||||
|
val jsont : t Jsont.t
|
||||||
|
|
||||||
|
(* only for encoding *)
|
||||||
|
val bin : t Bin.t
|
||||||
|
val bin_nbo : t Bin.t
|
||||||
|
|
|
||||||
24
src/api.ml
24
src/api.ml
|
|
@ -29,23 +29,33 @@ module ErrorDetail = struct
|
||||||
|> Jsont.Object.finish
|
|> Jsont.Object.finish
|
||||||
end
|
end
|
||||||
|
|
||||||
module HashCode = struct
|
module HashCode : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val hash : string -> t
|
||||||
|
val jsont : t Jsont.t
|
||||||
|
end = struct
|
||||||
type t = B32.t
|
type t = B32.t
|
||||||
|
|
||||||
|
let hash s =
|
||||||
|
let open Digestif.SHA256 in
|
||||||
|
s |> digest_string |> to_raw_string
|
||||||
|
|
||||||
let jsont = Jsont.of_of_string ~kind:"HashCode" B32.decode ~enc:B32.encode
|
let jsont = Jsont.of_of_string ~kind:"HashCode" B32.decode ~enc:B32.encode
|
||||||
end
|
end
|
||||||
|
|
||||||
module Amount = struct
|
|
||||||
include Amount
|
|
||||||
|
|
||||||
let jsont = Jsont.of_of_string ~kind:"Amount" of_string ~enc:to_string
|
|
||||||
end
|
|
||||||
|
|
||||||
module Timestamp = struct
|
module Timestamp = struct
|
||||||
type t =
|
type t =
|
||||||
| Seconds of float
|
| Seconds of float
|
||||||
| Never
|
| Never
|
||||||
|
|
||||||
|
(* TODO time
|
||||||
|
- time.ml
|
||||||
|
- check this
|
||||||
|
- what value for never?
|
||||||
|
- better way for conversion to bin_types? *)
|
||||||
|
let to_int64 t = match t with Never -> 0_L | Seconds v -> Int64.of_float v
|
||||||
|
let to_ptime t = Util.ptime_of_int64 @@ to_int64 t
|
||||||
let of_ptime p = Seconds (Ptime.to_float_s p)
|
let of_ptime p = Seconds (Ptime.to_float_s p)
|
||||||
|
|
||||||
let number_or_never_jsont =
|
let number_or_never_jsont =
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,15 @@ module INT64 = struct
|
||||||
|
|
||||||
let bin = Bin.neint64
|
let bin = Bin.neint64
|
||||||
let of_ptime v = Util.ptime_to_int64 v
|
let of_ptime v = Util.ptime_to_int64 v
|
||||||
|
let of_int64 i = i
|
||||||
end
|
end
|
||||||
|
|
||||||
module INT64_NBO = struct
|
module INT64_NBO = struct
|
||||||
type t = int64
|
type t = int64
|
||||||
|
|
||||||
let bin = Bin.beint64
|
let bin = Bin.beint64
|
||||||
let of_ptime = Util.ptime_to_int64
|
let of_ptime v = Util.ptime_to_int64 v
|
||||||
|
let of_int64 i = i
|
||||||
end
|
end
|
||||||
|
|
||||||
(* -- Time -- *)
|
(* -- Time -- *)
|
||||||
|
|
@ -80,6 +82,7 @@ module type Time_S = sig
|
||||||
|
|
||||||
val bin : t Bin.t
|
val bin : t Bin.t
|
||||||
val of_ptime : Ptime.t -> t
|
val of_ptime : Ptime.t -> t
|
||||||
|
val of_int64 : int64 -> t
|
||||||
end
|
end
|
||||||
|
|
||||||
module TimeAbsolute : Time_S = INT64
|
module TimeAbsolute : Time_S = INT64
|
||||||
|
|
@ -232,67 +235,14 @@ module AgeMask = struct
|
||||||
record (fun mask -> { mask }) |+ field beint32 (fun t -> t.mask) |> sealr
|
record (fun mask -> { mask }) |+ field beint32 (fun t -> t.mask) |> sealr
|
||||||
end
|
end
|
||||||
|
|
||||||
(* TODO
|
|
||||||
- why is the non-NBO version only used in TALER_WithdrawRequestPS?
|
|
||||||
- correctly do the padding and 0-termination
|
|
||||||
- handle "invalid" values *)
|
|
||||||
(* documentation: *)
|
|
||||||
(* Number of characters (plus 1 for 0-termination) for currency names.
|
|
||||||
typically an ISO 4217 currency code when an alphanumeric 3-digit code is used.
|
|
||||||
For regional currencies, the first character should be a "*" followed
|
|
||||||
by a region-specific name (i.e. "*BRETAGNEFR").
|
|
||||||
Currency codes are compared case-insensitively.
|
|
||||||
|
|
||||||
Currency string, left adjusted and padded with zeros.
|
|
||||||
All zeros for "invalid" values.
|
|
||||||
|
|
||||||
Name of the currency, using either a three-character ISO 4217 currency
|
|
||||||
code, or a regional currency identifier between 4 and 11 characters,
|
|
||||||
consisting of ASCII alphabetic characters ("a-zA-Z").
|
|
||||||
Should be padded to 12 bytes with 0-characters.
|
|
||||||
Currency codes are compared case-insensitively. *)
|
|
||||||
let currency_len = 12
|
|
||||||
|
|
||||||
(* TODO missing doc
|
|
||||||
found in src/include/taler/taler_amount_lib.h *)
|
|
||||||
module AmountP = struct
|
|
||||||
type t = {
|
|
||||||
value: int64;
|
|
||||||
fraction: int32;
|
|
||||||
currency: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
(* TODO BE here? *)
|
|
||||||
let bin =
|
|
||||||
let open Bin in
|
|
||||||
record (fun value fraction currency -> { value; fraction; currency })
|
|
||||||
|+ field beint64 (fun t -> t.value)
|
|
||||||
|+ field beint32 (fun t -> t.fraction)
|
|
||||||
|+ field (bytes currency_len) (fun t -> t.currency)
|
|
||||||
|> sealr
|
|
||||||
end
|
|
||||||
|
|
||||||
module AmountNBO = struct
|
|
||||||
type t = {
|
|
||||||
value: int64;
|
|
||||||
fraction: int32;
|
|
||||||
currency: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
let bin =
|
|
||||||
let open Bin in
|
|
||||||
record (fun value fraction currency -> { value; fraction; currency })
|
|
||||||
|+ field beint64 (fun t -> t.value)
|
|
||||||
|+ field beint32 (fun t -> t.fraction)
|
|
||||||
|+ field (bytes currency_len) (fun t -> t.currency)
|
|
||||||
|> sealr
|
|
||||||
end
|
|
||||||
|
|
||||||
(* TODO keep this?
|
(* TODO keep this?
|
||||||
some of those are actuall ecdhe, or union of eddsa|ecdhe *)
|
some of those are actuall ecdhe, or union of eddsa|ecdhe *)
|
||||||
module Aliases = struct
|
module Aliases = struct
|
||||||
(* TODO add Amount.bin *)
|
module AmountNBO = struct
|
||||||
module Amount = AmountP
|
type t = Amount.t
|
||||||
|
|
||||||
|
let bin = Amount.bin_nbo
|
||||||
|
end
|
||||||
|
|
||||||
(* - Keys - *)
|
(* - Keys - *)
|
||||||
module PursePublicKey = EddsaPublicKey
|
module PursePublicKey = EddsaPublicKey
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ module EddsaPrivateKey = struct
|
||||||
|
|
||||||
type t = priv
|
type t = priv
|
||||||
|
|
||||||
|
let pub_of_priv = pub_of_priv
|
||||||
let to_octets t = priv_to_octets t
|
let to_octets t = priv_to_octets t
|
||||||
let of_octets t = priv_of_octets t |> Result.get_ok
|
let of_octets t = priv_of_octets t |> Result.get_ok
|
||||||
let bin = Bin.map (Bin.bytes 32) of_octets to_octets
|
let bin = Bin.map (Bin.bytes 32) of_octets to_octets
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,66 @@ let download ~base_url ~output =
|
||||||
let wget = Cmd.(v "wget" % "-O" % output % uri) in
|
let wget = Cmd.(v "wget" % "-O" % output % uri) in
|
||||||
OS.Cmd.run wget
|
OS.Cmd.run wget
|
||||||
|
|
||||||
|
let setup ~output =
|
||||||
|
let output = Fpath.v output in
|
||||||
|
let () = Mirage_crypto_rng_unix.use_default () in
|
||||||
|
let priv, _pub = Mirage_crypto_ec.Ed25519.generate () in
|
||||||
|
let priv_data = Mirage_crypto_ec.Ed25519.priv_to_octets priv in
|
||||||
|
Bos.OS.File.write output priv_data
|
||||||
|
|
||||||
|
let _denom_signature master_priv master_pub
|
||||||
|
Api.FutureDenom.
|
||||||
|
{
|
||||||
|
section_name= _;
|
||||||
|
value;
|
||||||
|
stamp_start;
|
||||||
|
stamp_expire_withdraw;
|
||||||
|
stamp_expire_deposit;
|
||||||
|
stamp_expire_legal;
|
||||||
|
denom_pub;
|
||||||
|
fee_withdraw;
|
||||||
|
fee_deposit;
|
||||||
|
fee_refresh;
|
||||||
|
fee_refund= _;
|
||||||
|
(* TODO check sigs *)
|
||||||
|
denom_secmod_sig= _;
|
||||||
|
} =
|
||||||
|
let pub_octets =
|
||||||
|
let denom_pub =
|
||||||
|
match denom_pub with
|
||||||
|
| Rsa v -> v
|
||||||
|
| CS _ -> Fmt.failwith "CS key types are not supported."
|
||||||
|
in
|
||||||
|
let pub = denom_pub.Api.RsaDenominationKey.rsa_pub in
|
||||||
|
Crypto.RsaPublicKey.to_octets pub
|
||||||
|
in
|
||||||
|
let h_denom_pub = Api.HashCode.hash pub_octets in
|
||||||
|
let master_sig =
|
||||||
|
let open Bin_type in
|
||||||
|
let open Bin_signature.DenominationKeyValidityPS in
|
||||||
|
(* TODO time *)
|
||||||
|
let of_time ts : TimeAbsoluteNBO.t =
|
||||||
|
TimeAbsoluteNBO.of_int64 @@ Api.Timestamp.to_int64 ts
|
||||||
|
in
|
||||||
|
let denom_key_validity =
|
||||||
|
{
|
||||||
|
master= master_pub;
|
||||||
|
start= of_time stamp_start;
|
||||||
|
expire_withdraw= of_time stamp_expire_withdraw;
|
||||||
|
expire_spend= of_time stamp_expire_deposit;
|
||||||
|
expire_legal= of_time stamp_expire_legal;
|
||||||
|
value;
|
||||||
|
fee_withdraw;
|
||||||
|
fee_deposit;
|
||||||
|
fee_refresh;
|
||||||
|
denom_hash= DenominationHash.hash pub_octets;
|
||||||
|
}
|
||||||
|
in
|
||||||
|
let data = Bin.to_string bin denom_key_validity in
|
||||||
|
Crypto.EddsaSignature.sign ~key:master_priv data
|
||||||
|
in
|
||||||
|
Api.DenomSignature.{ h_denom_pub; master_sig }
|
||||||
|
|
||||||
let sign ~input ~output ~master_key =
|
let sign ~input ~output ~master_key =
|
||||||
let open Syntax in
|
let open Syntax in
|
||||||
let open Bos.OS in
|
let open Bos.OS in
|
||||||
|
|
@ -31,6 +91,24 @@ let sign ~input ~output ~master_key =
|
||||||
open Cmdliner
|
open Cmdliner
|
||||||
open Cmdliner.Term.Syntax
|
open Cmdliner.Term.Syntax
|
||||||
|
|
||||||
|
let setup_cmd =
|
||||||
|
let doc = "Generate offline master keys" in
|
||||||
|
let output =
|
||||||
|
let doc = "Output file for the generated private Eddsa key." in
|
||||||
|
Arg.(
|
||||||
|
value
|
||||||
|
& opt filepath "data/eddsa_master_offline"
|
||||||
|
& info [ "o"; "output" ] ~doc)
|
||||||
|
in
|
||||||
|
Cmd.make (Cmd.info "setup" ~version:"%%VERSION%%" ~doc)
|
||||||
|
@@
|
||||||
|
let+ output = output in
|
||||||
|
match setup ~output with
|
||||||
|
| Error (`Msg err) ->
|
||||||
|
Fmt.epr "Setup failure: %s@." err;
|
||||||
|
exit 1
|
||||||
|
| Ok () -> ()
|
||||||
|
|
||||||
let download_cmd =
|
let download_cmd =
|
||||||
let doc = "Downloads /management/keys/" in
|
let doc = "Downloads /management/keys/" in
|
||||||
let man =
|
let man =
|
||||||
|
|
@ -82,6 +160,7 @@ let sign_cmd =
|
||||||
exit 1
|
exit 1
|
||||||
| Ok () -> ()
|
| Ok () -> ()
|
||||||
|
|
||||||
let main () = Cmd.eval download_cmd
|
let main () = Cmd.eval setup_cmd
|
||||||
let _main () = Cmd.eval sign_cmd
|
let _main () = Cmd.eval download_cmd
|
||||||
|
let __main () = Cmd.eval sign_cmd
|
||||||
let () = if !Sys.interactive then () else exit (main ())
|
let () = if !Sys.interactive then () else exit (main ())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue