From ab82a357a959ba9b7575df2072c283703c699134 Mon Sep 17 00:00:00 2001 From: swrup Date: Fri, 28 Nov 2025 17:30:15 +0100 Subject: [PATCH] + wip sign_future_keys --- data/assets/default.config | 2 +- data/eddsa_master_offline | Bin 32 -> 32 bytes tools/dune | 2 +- tools/offline.ml | 85 +++++++++++-------------------------- tools/offline_signature.ml | 85 +++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 63 deletions(-) create mode 100644 tools/offline_signature.ml diff --git a/data/assets/default.config b/data/assets/default.config index 0c401640..ea32f28a 100644 --- a/data/assets/default.config +++ b/data/assets/default.config @@ -14,7 +14,7 @@ db = postgres attribute_encryption_key = "deadbeef" port = 3434 bind_to = localhost -master_public_key = "8MQF2XPWCKCW4199JFPE08X7Y9XAX21SF2HD8NZKXM3PY3CMCJ90====" +master_public_key = "SJ0NYND22VQP3MP7FM754RDX8HCKVWAXTHY9SQNBTPRJZ2SPM2S0====" stefan_abs = EUR:0.00 stefan_log = EUR:0.00 stefan_lin = 0.00 diff --git a/data/eddsa_master_offline b/data/eddsa_master_offline index 3e6eca7739f77d6ddb763fb9e4c2f1f6e9805d93..739df00753dec0a45457613e2fa155040b7b1640 100644 GIT binary patch literal 32 ocmeBTT_Rt)l0mH8LojFl=5=BInT@*|pKCD8z4+JNTQJuH0MexmUjP6A literal 32 pcmb==mA|syGW@}x*z)T>FDh?yK7Jp)YuB!A3t}G6=n75O001nj5-k7# diff --git a/tools/dune b/tools/dune index 3366e550..acb8c8bb 100644 --- a/tools/dune +++ b/tools/dune @@ -1,5 +1,5 @@ (executable (public_name offline) (name offline) - (modules offline) + (modules offline offline_signature) (libraries cmdliner bos fmt mirage-crypto ptime mte vif)) diff --git a/tools/offline.ml b/tools/offline.ml index 15a9743c..e8bdf5e9 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -3,6 +3,7 @@ - setup - sign *) (* doc: https://docs.taler.net/manpages/taler-exchange-offline.1.html *) +let version = "%%VERSION%%" let download ~base_url ~output = let open Bos in @@ -15,71 +16,28 @@ let download ~base_url ~output = 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, pub = Mirage_crypto_ec.Ed25519.generate () in + Fmt.pr "generated master public key:@\n%s@." + (Mirage_crypto_ec.Ed25519.pub_to_octets pub |> B32.encode); 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 - let denom_key_validity = - { - master= master_pub; - 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= 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 open Syntax in let open Bos.OS in let open Crypto in let input = Fpath.v input in - let _output = Fpath.v output in + let output = Fpath.v output in let master_key = Fpath.v master_key in let* input = File.read input |> unwrap_err_msg in let* master_key = File.read master_key |> unwrap_err_msg in - let _master_key = EddsaPrivateKey.of_octets master_key in - let* _future_key_response = Api.decode Api.FutureKeysResponse.jsont input in - (* TODO sign *) + let master_key = EddsaPrivateKey.of_octets master_key in + let* future_key_response = Api.decode Api.FutureKeysResponse.jsont input in + let master_signatures = + Offline_signature.master_signatures ~master_key future_key_response + in + let* s = Api.encode Api.MasterSignatures.jsont master_signatures in + let* () = File.write output s |> unwrap_err_msg in Ok () (* CLI *) @@ -96,7 +54,7 @@ let setup_cmd = & opt filepath "data/eddsa_master_offline" & info [ "o"; "output" ] ~doc) in - Cmd.make (Cmd.info "setup" ~version:"%%VERSION%%" ~doc) + Cmd.make (Cmd.info "setup" ~version ~doc) @@ let+ output = output in match setup ~output with @@ -118,7 +76,7 @@ let download_cmd = let doc = "Base url of the exchange." in Arg.(value & opt string "http://localhost:3434/" & info [ "base-url" ] ~doc) in - Cmd.make (Cmd.info "download" ~version:"%%VERSION%%" ~doc ~man) + Cmd.make (Cmd.info "download" ~version ~doc ~man) @@ let+ output = output and+ base_url = base_url in match download ~base_url ~output with @@ -147,7 +105,7 @@ let sign_cmd = & opt filepath "data/eddsa_master_offline" & info [ "master-key" ] ~doc) in - Cmd.make (Cmd.info "sign" ~version:"%%VERSION%%" ~doc) + Cmd.make (Cmd.info "sign" ~version ~doc) @@ let+ input = input and+ output = output and+ master_key = master_key in match sign ~input ~output ~master_key with @@ -156,7 +114,12 @@ let sign_cmd = exit 1 | Ok () -> () -let main () = Cmd.eval setup_cmd -let _main () = Cmd.eval download_cmd -let __main () = Cmd.eval sign_cmd -let () = if !Sys.interactive then () else exit (main ()) +let cli = + let info = + let doc = "MTE Offline CLI tool" in + Cmd.info "mte-offline" ~version ~doc + in + Cmd.group info [ setup_cmd; download_cmd; sign_cmd ] + +let main () = Cmd.eval cli +let () = exit (main ()) diff --git a/tools/offline_signature.ml b/tools/offline_signature.ml new file mode 100644 index 00000000..c01708b6 --- /dev/null +++ b/tools/offline_signature.ml @@ -0,0 +1,85 @@ +let denom_signature ~master_key + 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 + let master = Crypto.EddsaPrivateKey.(pub_of_priv master_key) in + let denom_hash = DenominationHash.hash pub_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 + |> Crypto.EddsaSignature.sign ~key:master_key + in + Api.DenomSignature.{ h_denom_pub; master_sig } + +let signkey_signature ~master_key + Api.FutureSignKey. + { + key; + stamp_start; + stamp_expire; + stamp_end; + (* TODO check sigs *) + signkey_secmod_sig= _; + } = + 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 + |> Crypto.EddsaSignature.sign ~key:master_key + in + Api.SignKeySignature.{ key; master_sig } + +let master_signatures ~master_key + Api.FutureKeysResponse. + { + future_denoms; + future_signkeys; + (* TODO check sigs *) + master_pub= _; + denom_secmod_public_key= _; + signkey_secmod_public_key= _; + } = + let denom_sigs = List.map (denom_signature ~master_key) future_denoms in + let signkey_sigs = List.map (signkey_signature ~master_key) future_signkeys in + Api.MasterSignatures.{ denom_sigs; signkey_sigs }