diff --git a/future_keys.json b/future_keys.json new file mode 100644 index 00000000..d31146c3 --- /dev/null +++ b/future_keys.json @@ -0,0 +1 @@ +{"future_denoms":[{"section_name":"kudo_1","value":"EUR:0.01","stamp_start":{"t_s":1764356753.7154291},"stamp_expire_withdraw":{"t_s":1795892753.7154291},"stamp_expire_deposit":{"t_s":1795892753.7154291},"stamp_expire_legal":{"t_s":1795892753.7154291},"denom_pub":{"cipher":"RSA","age_mask":0,"rsa_pub":"040002522NKSAQYZD012B42869VT8NDK6VRPEK58VMB9614ZYNDWGH0C34CX5865HBJTEQHRXVX6N55G644W235KCP7YPGAKJY5MGWA18TDFGTZVMQQ4CSAH7C47J48PFVKQHNY5SV07CX5B9V3651A2BVRJ27Z4QEFP12CTK3PYEN9A6P1A9PBJKDVDVMCQA6RCYK0EHYXVGP71EQ5MNZKAHE2RX694AZWFG0SNARY67RKBGDVNNKQWWCSR041A6M4HMNAXBC28K5N10P5AA1AMF33RVX6N0PCVGTMARRYW9YZ469GS02TJWF58WFPSXGQMN7M22XVCY17M3FCZFN2PRSD4VET0ZKSQMZD31J53187J7EZ4NK043D3ZKZ9RY03PZCJYXCN73KD4MX7S58VVY4KTCFQZ0000000004002==="},"fee_withdraw":"EUR:0.00","fee_deposit":"EUR:0.00","fee_refresh":"EUR:0.00","fee_refund":"EUR:0.00","denom_secmod_sig":"JXZY5CESM1KEWR63WQY82N8E58WN2G5R484PTCHXJD9J9WXDVFZKB8QR9FF8YD02PM93X1Y29FW9Z3EMN2Y7DJGWDTJWCAG3ZWCV80R="},{"section_name":"kudo_2","value":"EUR:0.02","stamp_start":{"t_s":1764356753.7550578},"stamp_expire_withdraw":{"t_s":1795892753.7550578},"stamp_expire_deposit":{"t_s":1795892753.7550578},"stamp_expire_legal":{"t_s":1795892753.7550578},"denom_pub":{"cipher":"RSA","age_mask":0,"rsa_pub":"0400025KTM91GTMNTB4ETARQWVHJB8KC9M3SKR894EFCRPN71X4F98HH56ECRSDH041P80YZ2GXGKRFZAAE1JKM7ARDE6TVJB08DXSKCKSTSHFQHAHDHBTZRT6VETF7W1FRJQ79B3EGC5Z4K6Z6T1ZZZ6CRXK8XJ9SBRVHJZCZCTEV6CPJT3C9R1DYK2HC2FAKYBGHB37W6D26G6QMKMW1T35HBTP4PCEQZFX9WD669CSS2MPSC6AQS22JY9Z5PSHCV4RC4FAPWFKKK8X8F2QXTG9M3725JY8RTGTF0J4Y1C0H10RNNYA9NJXAABV03F4J0MKZ854Z7KVZ29RJ3GVTZA6D7C9DQHV253BC3TSH49FXY23TK1GRRK1AHHVAR1QE95WVJG68ZXDXEEMJB7DX6H3T3EYER30000000004002==="},"fee_withdraw":"EUR:0.00","fee_deposit":"EUR:0.00","fee_refresh":"EUR:0.00","fee_refund":"EUR:0.00","denom_secmod_sig":"KCHYYANTMZNJQ73C8KF22NYSH7D34SNQ8ZQJSFHZYB32VC7JJ6DHWG71CPN1047JFX4TYJVBSB202QS39HM451TXNG1K3H0XHD4FY08="}],"future_signkeys":[{"key":"KNQEXXBEC5ERGH4EY2G3PCFBMPT89BD0XKZ7ZXSVC57DFJ4M9EJ0====","stamp_start":{"t_s":1764356753.7153544},"stamp_expire":{"t_s":1795892753.7153544},"stamp_end":{"t_s":1795892753.7153544},"signkey_secmod_sig":"YHNY93BT3KBTVE70ZVMBGNFN2YKEPQXAPR2G5YJVHXEYK7P3ZVKZQF43Q80JMPGZP5HGS46DANTZBHJ7DH8HNHPKB8BT8SJ7PD4DR2R="}],"master_pub":"SJ0NYND22VQP3MP7FM754RDX8HCKVWAXTHY9SQNBTPRJZ2SPM2S0====","denom_secmod_public_key":"HB5QVREEZT53JHYJQV1SCN7XR6XEEG7VH1E9E1CNFTJQZYKVXSPG====","signkey_secmod_public_key":"AEZCA4WKA5NS7ET5PBP10J75CTPXCYDA6DQD0Q66H9V4PERFBZE0===="} \ No newline at end of file diff --git a/master_signatures.json b/master_signatures.json new file mode 100644 index 00000000..4f1e37ab --- /dev/null +++ b/master_signatures.json @@ -0,0 +1 @@ +{"denom_sigs":[{"h_denom_pub":"2YHVTSJQ89Z3KEXZRBP8H7B0HAFDB9ARTY3G9FG6RJH1E1CWGC5XHBQ8KF0FA03E3QN1WJTHQ82EQH6W4KMTYVXGM44BBZ8QZRJYTN0=","master_sig":"77BVYM45Z6T66T3TGGDRZ20X8S9R5CFSKRAQQEYC3R8W8D6DS8EBVNCDCJNREXXZD7MCNFM3QMXQ51FYF2HZ9SFWSYVFKAYMYVWSA2R="},{"h_denom_pub":"W2MGGHS6PNS3GPCRNX6Z9380PJTM05FW50P8M2DPGSV7AGQ3RBGVM7VGBV3W86KH44PZRXMAXRHFRCQS82TVMBX8H8FXKNFMVWVKVQG=","master_sig":"DA849T2YH8FS9B3M399N0ZPTZT98JTSNNA7DZVJ0AC44YRTJ2BJW6VY4QKYYXS2S41CYZZ71958TSTGAAF1F81ZRMYQXDK2VV5JHP18="}],"signkey_sigs":[{"key":"KNQEXXBEC5ERGH4EY2G3PCFBMPT89BD0XKZ7ZXSVC57DFJ4M9EJ0====","master_sig":"K5AKPTJZEFC0CQ0BGWFZD5ZZKVMN5MW85TPE2RPDW5RJ9A3PFKE6ZZ1Z7EWEK0YEGB3YYH6VH0NKSNGVXR16NQB1GCX3YG0DJN97R18="}]} \ No newline at end of file diff --git a/src/amount.ml b/src/amount.ml index d208cfde..2b65bd2e 100644 --- a/src/amount.ml +++ b/src/amount.ml @@ -92,6 +92,13 @@ let of_string = let jsont = Jsont.of_of_string ~kind:"Amount" of_string ~enc:to_string let currency_len = 12 +let pad_currency s = + let len = String.length s in + assert (len <= 11); + let b = Bytes.make 12 '\x00' in + Bytes.blit_string s 0 b 0 len; + Bytes.to_string b + let bin = let open Bin in record (fun _value _fraction _currency -> @@ -99,7 +106,7 @@ let bin = assert false) |+ field neint64 (fun t -> t.value) |+ field neint32 (fun t -> t.fraction) - |+ field (bytes currency_len) (fun t -> t.currency) + |+ field (bytes currency_len) (fun t -> pad_currency t.currency) |> sealr let bin_nbo = @@ -107,5 +114,5 @@ let bin_nbo = 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) + |+ field (bytes currency_len) (fun t -> pad_currency t.currency) |> sealr diff --git a/src/api.ml b/src/api.ml index 60954791..f6dd4427 100644 --- a/src/api.ml +++ b/src/api.ml @@ -38,7 +38,7 @@ end = struct type t = B32.t let hash s = - let open Digestif.SHA256 in + let open Digestif.SHA512 in s |> digest_string |> to_raw_string let jsont = Jsont.of_of_string ~kind:"HashCode" B32.decode ~enc:B32.encode diff --git a/src/bin_type.ml b/src/bin_type.ml index 652a0eab..38d047b5 100644 --- a/src/bin_type.ml +++ b/src/bin_type.ml @@ -120,7 +120,11 @@ module Hash_64 = struct | false -> Fmt.failwith "Hash.of_octets failure: data is not 64 bytes" | true -> Digestif.SHA512.of_raw_string s - let to_octets = Digestif.SHA512.to_raw_string + let to_octets v = + let s = Digestif.SHA512.to_raw_string v in + match String.length s = 64 with + | false -> Fmt.failwith "Hash.to_octets failure: data is not 64 bytes" + | true -> s let bin = let open Bin in diff --git a/src/crypto.ml b/src/crypto.ml index 1e2f7e2c..639a0210 100644 --- a/src/crypto.ml +++ b/src/crypto.ml @@ -113,17 +113,19 @@ module RsaPublicKey = struct String.sub src pos len |> rev_string len |> Z.of_bits let to_octets ({ n; e } : Mirage_crypto_pk.Rsa.pub) = - let n_len = Z.size n in - let e_len = Z.size e in + let n = Z.to_bits n in + let e = Z.to_bits e in + let n_len = String.length n in + let e_len = String.length e in let len = 4 + n_len + e_len in let b = Bytes.make len '\x00' in Bytes.set_uint16_be b 0 n_len; Bytes.set_uint16_be b 2 e_len; - let n = Z.to_bits n |> rev_string n_len in - let e = Z.to_bits e |> rev_string e_len in + let n = rev_string n_len n in + let e = rev_string e_len e in Bytes.blit_string n 0 b 4 n_len; Bytes.blit_string e 0 b (4 + n_len) e_len; - Bytes.unsafe_to_string b + Bytes.to_string b let of_octets = let check = function @@ -131,8 +133,6 @@ module RsaPublicKey = struct | true -> Ok () in fun s -> - Result.get_ok - @@ let open Syntax in let len = String.length s in let* () = check (len >= 4) in @@ -142,6 +142,11 @@ module RsaPublicKey = struct let n = z_of_bits_be s 4 n_len in let e = z_of_bits_be s (4 + n_len) e_len in Mirage_crypto_pk.Rsa.pub ~n ~e |> unwrap_err_msg + + let of_octets s = + match of_octets s with + | Error e -> Fmt.failwith "RsaPublicKey.of_octets failure: %s@." e + | Ok v -> v end include Binary diff --git a/src/management.ml b/src/management.ml index b89fed1c..c2bd0cd1 100644 --- a/src/management.ml +++ b/src/management.ml @@ -109,3 +109,10 @@ let keys req server _env = let* () = with_string req s in let* () = add ~field:"content-type" "application/json" in respond `OK + +let keys_post req _server _env = + let open Vif.Response in + let open Syntax in + let* () = with_string req "todo~~" in + let* () = add ~field:"content-type" "application/json" in + respond `OK diff --git a/src/mte.ml b/src/mte.ml index 9cf40473..bcbd2c4f 100644 --- a/src/mte.ml +++ b/src/mte.ml @@ -107,12 +107,15 @@ let hello req _server _env = let routes = let open Vif.Uri in let open Vif.Route in - (*let open Vif.Type in*) + let open Vif.Type in [ get (rel /?? nil) --> hello; get (rel / "terms" /?? nil) --> Static.terms; get (rel / "privacy" /?? nil) --> Static.privacy; get (rel / "management" / "keys" /?? nil) --> Management.keys; - get (rel / "db_test" /?? nil) --> Database.test; + post + (json_encoding Api.MasterSignatures.jsont) + (rel / "management" / "keys" /?? nil) + --> Management.keys_post; get (rel / "db_test" /?? nil) --> Database.test; get (rel / "db_activate" /?? nil) --> Database.test_activate; ] diff --git a/tools/offline.ml b/tools/offline.ml index e8bdf5e9..2c8aacb3 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -13,6 +13,22 @@ let download ~base_url ~output = let wget = Cmd.(v "wget" % "-O" % output % uri) in OS.Cmd.run wget +let upload ~base_url ~input = + let open Bos in + let uri = + Uri.with_path (Uri.of_string base_url) "/management/keys/" |> Uri.to_string + in + let wget = + Cmd.( + v "wget" + % "--method=POST" + % "--header='Content-Type: application/json'" + % "--post-file" + % input + % uri) + in + OS.Cmd.run wget + let setup ~output = let output = Fpath.v output in let () = Mirage_crypto_rng_unix.use_default () in @@ -64,7 +80,7 @@ let setup_cmd = | Ok () -> () let download_cmd = - let doc = "Downloads /management/keys/" in + let doc = "GET /management/keys/" in let man = [ `S Manpage.s_description; `P "$(cmd) download /management/keys." ] in @@ -85,6 +101,29 @@ let download_cmd = exit 1 | Ok () -> () +let upload_cmd = + let doc = "POST /management/keys/" in + let man = + [ `S Manpage.s_description; `P "$(cmd) upload /management/keys." ] + in + let input = + let doc = "Input file." in + Arg.( + value & opt filepath "master_signatures.json" & info [ "i"; "input" ] ~doc) + in + let base_url = + let doc = "Base url of the exchange." in + Arg.(value & opt string "http://localhost:3434/" & info [ "base-url" ] ~doc) + in + Cmd.make (Cmd.info "upload" ~version ~doc ~man) + @@ + let+ input = input and+ base_url = base_url in + match upload ~base_url ~input with + | Error (`Msg err) -> + Fmt.epr "Upload failure: %s@." err; + exit 1 + | Ok () -> () + let sign_cmd = let doc = "Sign FutureKeysResponse." in let input = @@ -119,7 +158,7 @@ let cli = let doc = "MTE Offline CLI tool" in Cmd.info "mte-offline" ~version ~doc in - Cmd.group info [ setup_cmd; download_cmd; sign_cmd ] + Cmd.group info [ setup_cmd; download_cmd; sign_cmd; upload_cmd ] let main () = Cmd.eval cli let () = exit (main ()) diff --git a/tools/offline_signature.ml b/tools/offline_signature.ml index c01708b6..3e9f4b25 100644 --- a/tools/offline_signature.ml +++ b/tools/offline_signature.ml @@ -25,11 +25,11 @@ let denom_signature ~master_key Crypto.RsaPublicKey.to_octets pub in let h_denom_pub = Api.HashCode.hash pub_octets in + let master = Crypto.EddsaPrivateKey.(pub_of_priv master_key) in + let denom_hash = Bin_type.DenominationHash.hash pub_octets in let master_sig = - let open Bin_type in + (*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;