From 361b3db3e8cad27b5b1753d533e31c9edd009adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Henry?= Date: Sat, 26 May 2018 12:51:51 +0200 Subject: [PATCH] Signer: only accept B58encoded-pkh as parameters --- src/bin_signer/handler.ml | 35 ++++----- src/bin_signer/https_daemon.ml | 10 +-- src/bin_signer/socket_daemon.ml | 6 +- src/lib_client_base/client_keys.ml | 12 +++ src/lib_client_base/client_keys.mli | 5 ++ src/lib_signer_backends/remote.ml | 69 +++++++++-------- src/lib_signer_services/signer_messages.ml | 85 +++++++++++---------- src/lib_signer_services/signer_messages.mli | 26 +++---- src/lib_signer_services/signer_services.ml | 19 +++-- src/lib_signer_services/signer_services.mli | 8 +- 10 files changed, 144 insertions(+), 131 deletions(-) diff --git a/src/bin_signer/handler.ml b/src/bin_signer/handler.ml index 682a5579e..3bac85ff1 100644 --- a/src/bin_signer/handler.ml +++ b/src/bin_signer/handler.ml @@ -7,29 +7,22 @@ (* *) (**************************************************************************) -open Signer_messages - let log = Logging.Client.Sign.lwt_log_notice -let sign (cctxt : #Client_context.wallet) key data = - log "Request for signing %d bytes of data for key %s, magic byte = %02X" +let sign (cctxt : #Client_context.wallet) pkh data = + log "Request for signing %d bytes of data for key %a, magic byte = %02X" (MBytes.length data) - key + Signature.Public_key_hash.pp pkh (MBytes.get_uint8 data 0) >>= fun () -> - Client_keys.alias_keys cctxt key >>=? function - | None -> failwith "Unknown alias key (%s)" key - | Some (_, _, None) -> failwith "Unknown secret key (%s)" key - | Some (_, _, Some skloc) -> - log "Signing data for key %s" key >>= fun () -> - Client_keys.sign cctxt skloc data >>=? fun signature -> - return { Sign.Response.signature = signature } + Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) -> + log "Signing data for key %s" name >>= fun () -> + Client_keys.sign cctxt sk_uri data >>=? fun signature -> + return signature -let public_key (cctxt : #Client_context.wallet) key = - Client_keys.alias_keys cctxt key >>=? function - | None -> failwith "Unkown alias key (%s)" key - | Some (public_key_hash, _, _) -> - log "Found public key hash %a for key %s" - Signature.Public_key_hash.pp public_key_hash key >>= fun () -> - Client_keys.get_key cctxt public_key_hash >>=? fun (_, public_key, _) -> - log "Found public key for key %s" key >>= fun () -> - return { Public_key.Response.public_key } +let public_key (cctxt : #Client_context.wallet) pkh = + log "Request for public key %a" + Signature.Public_key_hash.pp pkh >>= fun () -> + Client_keys.get_public_key cctxt pkh >>=? fun (name, pk) -> + log "Found public key for hash %a (name: %s)" + Signature.Public_key_hash.pp pkh name >>= fun () -> + return pk diff --git a/src/bin_signer/https_daemon.ml b/src/bin_signer/https_daemon.ml index b7e3b8156..b696e4cb0 100644 --- a/src/bin_signer/https_daemon.ml +++ b/src/bin_signer/https_daemon.ml @@ -9,18 +9,18 @@ let log = Logging.Client.Sign.lwt_log_notice -let run (cctxt : #Client_context.io_wallet) ~host ~port ~cert ~key = +let run (cctxt : #Client_context.wallet) ~host ~port ~cert ~key = log "Accepting HTTPS requests on port %d" port >>= fun () -> let mode : Conduit_lwt_unix.server = `TLS (`Crt_file_path cert, `Key_file_path key, `No_password, `Port port) in let dir = RPC_directory.empty in let dir = - RPC_directory.register0 dir Signer_services.sign begin fun () req -> - Handler.sign cctxt req.key req.data + RPC_directory.register1 dir Signer_services.sign begin fun pkh () data -> + Handler.sign cctxt pkh data end in let dir = - RPC_directory.register0 dir Signer_services.public_key begin fun () req -> - Handler.public_key cctxt req.key + RPC_directory.register1 dir Signer_services.public_key begin fun pkh () () -> + Handler.public_key cctxt pkh end in Lwt.catch (fun () -> diff --git a/src/bin_signer/socket_daemon.ml b/src/bin_signer/socket_daemon.ml index d41cbd940..75ceb585f 100644 --- a/src/bin_signer/socket_daemon.ml +++ b/src/bin_signer/socket_daemon.ml @@ -19,13 +19,13 @@ let run (cctxt : #Client_context.wallet) path = Lwt_utils_unix.Socket.recv fd Request.encoding >>=? function | Sign req -> let encoding = result_encoding Sign.Response.encoding in - Handler.sign cctxt req.key req.data >>= fun res -> + Handler.sign cctxt req.pkh req.data >>= fun res -> Lwt_utils_unix.Socket.send fd encoding res >>= fun _ -> Lwt_unix.close fd >>= fun () -> return () - | Public_key req -> + | Public_key pkh -> let encoding = result_encoding Public_key.Response.encoding in - Handler.public_key cctxt req.key >>= fun res -> + Handler.public_key cctxt pkh >>= fun res -> Lwt_utils_unix.Socket.send fd encoding res >>= fun _ -> Lwt_unix.close fd >>= fun () -> return () diff --git a/src/lib_client_base/client_keys.ml b/src/lib_client_base/client_keys.ml index fb86253d3..991373853 100644 --- a/src/lib_client_base/client_keys.ml +++ b/src/lib_client_base/client_keys.ml @@ -274,6 +274,18 @@ let get_key (cctxt : #Client_context.wallet) pkh = Signer.public_key pk >>=? fun pk -> return (n, pk, sk) +let get_public_key (cctxt : #Client_context.wallet) pkh = + Public_key_hash.rev_find cctxt pkh >>=? function + | None -> failwith "no keys for the source contract manager" + | Some n -> + Public_key.find cctxt n >>=? fun pk -> + let scheme = Public_key_locator.scheme pk in + find_signer_for_key cctxt ~scheme >>=? fun signer -> + let module Signer = (val signer : SIGNER) in + Signer.pk_of_locator pk >>=? fun pk -> + Signer.public_key pk >>=? fun pk -> + return (n, pk) + let get_keys (wallet : #Client_context.io_wallet) = Secret_key.load wallet >>=? fun sks -> Lwt_list.filter_map_s begin fun (name, sk) -> diff --git a/src/lib_client_base/client_keys.mli b/src/lib_client_base/client_keys.mli index de13ceb32..e9f478fb9 100644 --- a/src/lib_client_base/client_keys.mli +++ b/src/lib_client_base/client_keys.mli @@ -150,6 +150,11 @@ val get_key: Public_key_hash.t -> (string * Signature.Public_key.t * sk_locator) tzresult Lwt.t +val get_public_key: + #Client_context.io_wallet -> + Public_key_hash.t -> + (string * Signature.Public_key.t) tzresult Lwt.t + val get_keys: #Client_context.io_wallet -> (string * Public_key_hash.t * Signature.Public_key.t * sk_locator) list tzresult Lwt.t diff --git a/src/lib_signer_backends/remote.ml b/src/lib_signer_backends/remote.ml index f33950345..195f8d194 100644 --- a/src/lib_signer_backends/remote.ml +++ b/src/lib_signer_backends/remote.ml @@ -10,45 +10,44 @@ open Client_keys open Signer_messages -let call host port service arg = - RPC_client.call_service - Media_type.all_media_types - ~base: (Uri.of_string (Format.asprintf "https://%s:%d" host port)) - service () () arg - type path = | Socket of Lwt_utils_unix.Socket.addr | Https of string * int -let socket_sign path key data = - let req = { Sign.Request.key = key ; data } in +let socket_sign path pkh data = + let req = { Sign.Request.pkh ; data } in Lwt_utils_unix.Socket.connect path >>=? fun conn -> Lwt_utils_unix.Socket.send conn Request.encoding (Request.Sign req) >>=? fun () -> let encoding = result_encoding Sign.Response.encoding in - Lwt_utils_unix.Socket.recv conn encoding >>=? function - | Error err -> Lwt.return (Error err) - | Ok res -> Lwt_unix.close conn >>= fun () -> return res.signature + Lwt_utils_unix.Socket.recv conn encoding >>=? fun res -> + Lwt_unix.close conn >>= fun () -> + Lwt.return res -let socket_request_public_key path key = - let req = { Public_key.Request.key = key } in +let socket_request_public_key path pkh = Lwt_utils_unix.Socket.connect path >>=? fun conn -> - Lwt_utils_unix.Socket.send conn Request.encoding (Request.Public_key req) >>=? fun () -> + Lwt_utils_unix.Socket.send conn Request.encoding (Request.Public_key pkh) >>=? fun () -> let encoding = result_encoding Public_key.Response.encoding in - Lwt_utils_unix.Socket.recv conn encoding >>=? function - | Error err -> Lwt.return (Error err) - | Ok res -> Lwt_unix.close conn >>= fun () -> return res.public_key + Lwt_utils_unix.Socket.recv conn encoding >>=? fun res -> + Lwt_unix.close conn >>= fun () -> + Lwt.return res -let sign path key data = match path with - | Socket path -> socket_sign path key data +let sign path pkh data = + match path with + | Socket path -> socket_sign path pkh data | Https (host, port) -> - call host port Signer_services.sign { key ; data } >>=? fun res -> - return res.signature + RPC_client.call_service + Media_type.all_media_types + ~base: (Uri.of_string (Format.asprintf "https://%s:%d" host port)) + Signer_services.sign ((), pkh) () data -let request_public_key path key = match path with - | Socket path -> socket_request_public_key path key +let request_public_key path pkh = + match path with + | Socket path -> socket_request_public_key path pkh | Https (host, port) -> - call host port Signer_services.public_key { key } >>=? fun res -> - return res.public_key + RPC_client.call_service + Media_type.all_media_types + ~base: (Uri.of_string (Format.asprintf "https://%s:%d" host port)) + Signer_services.public_key ((), pkh) () () module Remote_signer : SIGNER = struct let scheme = "remote" @@ -70,7 +69,7 @@ module Remote_signer : SIGNER = struct that get evaluated to default values '$HOME/.tezos-signer-socket', \ localhost and 6732, and can be set later on." - type key_path = path * key + type key_path = path * Signature.Public_key_hash.t (* secret key is the identifier of the location key identifier *) type secret_key = key_path @@ -84,18 +83,22 @@ module Remote_signer : SIGNER = struct let path_of_human_input = function | "unix" :: key :: [] -> - return (Socket (Unix "$TEZOS_SIGNER_UNIX_PATH"), key) + return (Socket (Unix "$TEZOS_SIGNER_UNIX_PATH"), + Signature.Public_key_hash.of_b58check_exn key) | "unix" :: file :: key :: [] -> - return (Socket (Unix file), key) + return (Socket (Unix file), + Signature.Public_key_hash.of_b58check_exn key) | "tcp" :: host :: port :: key :: [] -> - return (Socket (Tcp (host, int_of_string port)), key) + return (Socket (Tcp (host, int_of_string port)), + Signature.Public_key_hash.of_b58check_exn key) (* Temporary FIXME *) (* | "tcp" :: host :: key :: [] -> *) (* return (Socket (Tcp (host, "$TEZOS_SIGNER_TCP_PORT")), key) *) (* | "tcp" :: key :: [] -> *) (* return (Socket (Tcp ("$TEZOS_SIGNER_TCP_HOST", "$TEZOS_SIGNER_TCP_PORT")), key) *) | "https" :: host :: port :: key :: [] -> - return (Https (host, int_of_string port), key) + return (Https (host, int_of_string port), + Signature.Public_key_hash.of_b58check_exn key) (* Temporary FIXME *) (* | "https" :: host :: key :: [] -> *) (* return (Https (host, "$TEZOS_SIGNER_HTTPS_PORT"), key) *) @@ -108,9 +111,9 @@ module Remote_signer : SIGNER = struct Format.pp_print_text description let locator_of_path = function - | Socket (Unix path), key -> [ "unix" ; path ; key ] - | Socket (Tcp (host, port)), key -> [ "tcp" ; host ; string_of_int port ; key ] - | Https (host, port), key -> [ "https" ; host ; string_of_int port ; key ] + | Socket (Unix path), key -> [ "unix" ; path ; Signature.Public_key_hash.to_b58check key ] + | Socket (Tcp (host, port)), key -> [ "tcp" ; host ; string_of_int port ; Signature.Public_key_hash.to_b58check key ] + | Https (host, port), key -> [ "https" ; host ; string_of_int port ; Signature.Public_key_hash.to_b58check key ] let pk_locator_of_human_input _cctxt path = path_of_human_input path >>=? fun pk -> diff --git a/src/lib_signer_services/signer_messages.ml b/src/lib_signer_services/signer_messages.ml index 42e919eaf..9c18e3efb 100644 --- a/src/lib_signer_services/signer_messages.ml +++ b/src/lib_signer_services/signer_messages.ml @@ -7,7 +7,7 @@ (* *) (**************************************************************************) -type error += Unkwnon_alias_key of string +type error += Unknown_alias_key of string let () = register_error_kind `Permanent @@ -17,84 +17,85 @@ let () = ~pp: (fun ppf s -> Format.fprintf ppf "The key %s does not is not known on the remote signer" s) Data_encoding.(obj1 (req "value" string)) - (function Unkwnon_alias_key s -> Some s | _ -> None) - (fun s -> Unkwnon_alias_key s) - -type key = string + (function Unknown_alias_key s -> Some s | _ -> None) + (fun s -> Unknown_alias_key s) module Sign = struct + module Request = struct + type t = { - key : key ; + pkh: Signature.Public_key_hash.t ; data: MBytes.t ; } let encoding = let open Data_encoding in conv - (fun { key ; data } -> - ( key, data)) - (fun (key, data) -> - { key ; data }) + (fun { pkh ; data } -> + (pkh, data)) + (fun (pkh, data) -> + { pkh ; data }) (obj2 - (req "key" string) + (req "pkh" Signature.Public_key_hash.encoding) (req "data" bytes)) + end module Response = struct - type t = { - signature : Signature.t - } + + type t = Signature.t let encoding = - let open Data_encoding in - conv - (fun { signature } -> (signature)) - (fun (signature) -> { signature }) - (obj1 (req "signature" Signature.encoding)) + Data_encoding.(obj1 (req "signature" Signature.encoding)) + end + end module Public_key = struct + module Request = struct - type t = { - key : key ; - } + + type t = Signature.Public_key_hash.t let encoding = - let open Data_encoding in - conv - (fun { key } -> key) - (fun key -> { key }) - (obj1 (req "key" string)) + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + end module Response = struct - type t = { - public_key : Signature.Public_key.t ; - } + + type t = Signature.Public_key.t let encoding = - let open Data_encoding in - conv - (fun { public_key } -> public_key) - (fun public_key -> { public_key }) - (obj1 (req "pubkey" Signature.Public_key.encoding)) + Data_encoding.(obj1 (req "pubkey" Signature.Public_key.encoding)) + end + end module Request = struct + type t = | Sign of Sign.Request.t | Public_key of Public_key.Request.t let encoding = let open Data_encoding in - union - [ case (Tag 0) (merge_objs (obj1 (req "kind" (constant "sign"))) Sign.Request.encoding) - (function Sign req -> Some ((), req) | _ -> None) - (fun ((), req) -> Sign req) ; - case (Tag 1) (merge_objs (obj1 (req "kind" (constant "public_key"))) Public_key.Request.encoding) - (function Public_key req -> Some ((), req) | _ -> None) - (fun ((), req) -> Public_key req) ] + union [ + case (Tag 0) + (merge_objs + (obj1 (req "kind" (constant "sign"))) + Sign.Request.encoding) + (function Sign req -> Some ((), req) | _ -> None) + (fun ((), req) -> Sign req) ; + case (Tag 1) + (merge_objs + (obj1 (req "kind" (constant "public_key"))) + Public_key.Request.encoding) + (function Public_key req -> Some ((), req) | _ -> None) + (fun ((), req) -> Public_key req) ; + ] + end diff --git a/src/lib_signer_services/signer_messages.mli b/src/lib_signer_services/signer_messages.mli index 7d5d5407b..f07324558 100644 --- a/src/lib_signer_services/signer_messages.mli +++ b/src/lib_signer_services/signer_messages.mli @@ -7,44 +7,44 @@ (* *) (**************************************************************************) -type error += Unkwnon_alias_key of string - -type key = string +type error += Unknown_alias_key of string module Sign : sig + module Request : sig type t = { - key : key ; + pkh: Signature.Public_key_hash.t ; data: MBytes.t ; } val encoding : t Data_encoding.t end + module Response : sig - type t = { - signature : Signature.t ; - } + type t = Signature.t val encoding : t Data_encoding.t end + end module Public_key : sig + module Request : sig - type t = { - key : key ; - } + type t = Signature.Public_key_hash.t val encoding : t Data_encoding.t end + module Response : sig - type t = { - public_key : Signature.Public_key.t ; - } + type t = Signature.Public_key.t val encoding : t Data_encoding.t end + end module Request : sig + type t = | Sign of Sign.Request.t | Public_key of Public_key.Request.t val encoding : t Data_encoding.t + end diff --git a/src/lib_signer_services/signer_services.ml b/src/lib_signer_services/signer_services.ml index 769241eee..807d0a795 100644 --- a/src/lib_signer_services/signer_services.ml +++ b/src/lib_signer_services/signer_services.ml @@ -7,18 +7,17 @@ (* *) (**************************************************************************) -open Signer_messages - -let sign = RPC_service.post_service +let sign = + RPC_service.post_service ~description: "Sign a piece of data with a given remote key" ~query: RPC_query.empty - ~input: Sign.Request.encoding - ~output: Sign.Response.encoding - RPC_path.(root / "sign") + ~input: Data_encoding.bytes + ~output: Data_encoding.(obj1 (req "signature" Signature.encoding)) + RPC_path.(root /: Signature.Public_key_hash.rpc_arg) -let public_key = RPC_service.post_service +let public_key = + RPC_service.get_service ~description: "Retrieve the public key of a given remote key" ~query: RPC_query.empty - ~input: Public_key.Request.encoding - ~output: Public_key.Response.encoding - RPC_path.(root / "public_key") + ~output: Data_encoding.(obj1 (req "public_key" Signature.Public_key.encoding)) + RPC_path.(root /: Signature.Public_key_hash.rpc_arg) diff --git a/src/lib_signer_services/signer_services.mli b/src/lib_signer_services/signer_services.mli index 9b8808a98..155e76e51 100644 --- a/src/lib_signer_services/signer_services.mli +++ b/src/lib_signer_services/signer_services.mli @@ -7,10 +7,10 @@ (* *) (**************************************************************************) -open Signer_messages - val sign : - ([ `POST ], unit, unit, unit, Sign.Request.t, Sign.Response.t) RPC_service.t + ([ `POST ], unit, unit * Signature.Public_key_hash.t, + unit, MBytes.t, Signature.t) RPC_service.t val public_key : - ([ `POST ], unit, unit, unit, Public_key.Request.t, Public_key.Response.t) RPC_service.t + ([ `GET ], unit, unit * Signature.Public_key_hash.t, + unit, unit, Signature.Public_key.t) RPC_service.t