Signer: only accept B58encoded-pkh as parameters

This commit is contained in:
Grégoire Henry 2018-05-26 12:51:51 +02:00
parent e8fb2bf515
commit 361b3db3e8
10 changed files with 144 additions and 131 deletions

View File

@ -7,29 +7,22 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
open Signer_messages
let log = Logging.Client.Sign.lwt_log_notice let log = Logging.Client.Sign.lwt_log_notice
let sign (cctxt : #Client_context.wallet) key data = let sign (cctxt : #Client_context.wallet) pkh data =
log "Request for signing %d bytes of data for key %s, magic byte = %02X" log "Request for signing %d bytes of data for key %a, magic byte = %02X"
(MBytes.length data) (MBytes.length data)
key Signature.Public_key_hash.pp pkh
(MBytes.get_uint8 data 0) >>= fun () -> (MBytes.get_uint8 data 0) >>= fun () ->
Client_keys.alias_keys cctxt key >>=? function Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
| None -> failwith "Unknown alias key (%s)" key log "Signing data for key %s" name >>= fun () ->
| Some (_, _, None) -> failwith "Unknown secret key (%s)" key Client_keys.sign cctxt sk_uri data >>=? fun signature ->
| Some (_, _, Some skloc) -> return signature
log "Signing data for key %s" key >>= fun () ->
Client_keys.sign cctxt skloc data >>=? fun signature ->
return { Sign.Response.signature = signature }
let public_key (cctxt : #Client_context.wallet) key = let public_key (cctxt : #Client_context.wallet) pkh =
Client_keys.alias_keys cctxt key >>=? function log "Request for public key %a"
| None -> failwith "Unkown alias key (%s)" key Signature.Public_key_hash.pp pkh >>= fun () ->
| Some (public_key_hash, _, _) -> Client_keys.get_public_key cctxt pkh >>=? fun (name, pk) ->
log "Found public key hash %a for key %s" log "Found public key for hash %a (name: %s)"
Signature.Public_key_hash.pp public_key_hash key >>= fun () -> Signature.Public_key_hash.pp pkh name >>= fun () ->
Client_keys.get_key cctxt public_key_hash >>=? fun (_, public_key, _) -> return pk
log "Found public key for key %s" key >>= fun () ->
return { Public_key.Response.public_key }

View File

@ -9,18 +9,18 @@
let log = Logging.Client.Sign.lwt_log_notice 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 () -> log "Accepting HTTPS requests on port %d" port >>= fun () ->
let mode : Conduit_lwt_unix.server = let mode : Conduit_lwt_unix.server =
`TLS (`Crt_file_path cert, `Key_file_path key, `No_password, `Port port) in `TLS (`Crt_file_path cert, `Key_file_path key, `No_password, `Port port) in
let dir = RPC_directory.empty in let dir = RPC_directory.empty in
let dir = let dir =
RPC_directory.register0 dir Signer_services.sign begin fun () req -> RPC_directory.register1 dir Signer_services.sign begin fun pkh () data ->
Handler.sign cctxt req.key req.data Handler.sign cctxt pkh data
end in end in
let dir = let dir =
RPC_directory.register0 dir Signer_services.public_key begin fun () req -> RPC_directory.register1 dir Signer_services.public_key begin fun pkh () () ->
Handler.public_key cctxt req.key Handler.public_key cctxt pkh
end in end in
Lwt.catch Lwt.catch
(fun () -> (fun () ->

View File

@ -19,13 +19,13 @@ let run (cctxt : #Client_context.wallet) path =
Lwt_utils_unix.Socket.recv fd Request.encoding >>=? function Lwt_utils_unix.Socket.recv fd Request.encoding >>=? function
| Sign req -> | Sign req ->
let encoding = result_encoding Sign.Response.encoding in 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_utils_unix.Socket.send fd encoding res >>= fun _ ->
Lwt_unix.close fd >>= fun () -> Lwt_unix.close fd >>= fun () ->
return () return ()
| Public_key req -> | Public_key pkh ->
let encoding = result_encoding Public_key.Response.encoding in 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_utils_unix.Socket.send fd encoding res >>= fun _ ->
Lwt_unix.close fd >>= fun () -> Lwt_unix.close fd >>= fun () ->
return () return ()

View File

@ -274,6 +274,18 @@ let get_key (cctxt : #Client_context.wallet) pkh =
Signer.public_key pk >>=? fun pk -> Signer.public_key pk >>=? fun pk ->
return (n, pk, sk) 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) = let get_keys (wallet : #Client_context.io_wallet) =
Secret_key.load wallet >>=? fun sks -> Secret_key.load wallet >>=? fun sks ->
Lwt_list.filter_map_s begin fun (name, sk) -> Lwt_list.filter_map_s begin fun (name, sk) ->

View File

@ -150,6 +150,11 @@ val get_key:
Public_key_hash.t -> Public_key_hash.t ->
(string * Signature.Public_key.t * sk_locator) tzresult Lwt.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: val get_keys:
#Client_context.io_wallet -> #Client_context.io_wallet ->
(string * Public_key_hash.t * Signature.Public_key.t * sk_locator) list tzresult Lwt.t (string * Public_key_hash.t * Signature.Public_key.t * sk_locator) list tzresult Lwt.t

View File

@ -10,45 +10,44 @@
open Client_keys open Client_keys
open Signer_messages 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 = type path =
| Socket of Lwt_utils_unix.Socket.addr | Socket of Lwt_utils_unix.Socket.addr
| Https of string * int | Https of string * int
let socket_sign path key data = let socket_sign path pkh data =
let req = { Sign.Request.key = key ; data } in let req = { Sign.Request.pkh ; data } in
Lwt_utils_unix.Socket.connect path >>=? fun conn -> Lwt_utils_unix.Socket.connect path >>=? fun conn ->
Lwt_utils_unix.Socket.send conn Request.encoding (Request.Sign req) >>=? fun () -> Lwt_utils_unix.Socket.send conn Request.encoding (Request.Sign req) >>=? fun () ->
let encoding = result_encoding Sign.Response.encoding in let encoding = result_encoding Sign.Response.encoding in
Lwt_utils_unix.Socket.recv conn encoding >>=? function Lwt_utils_unix.Socket.recv conn encoding >>=? fun res ->
| Error err -> Lwt.return (Error err) Lwt_unix.close conn >>= fun () ->
| Ok res -> Lwt_unix.close conn >>= fun () -> return res.signature Lwt.return res
let socket_request_public_key path key = let socket_request_public_key path pkh =
let req = { Public_key.Request.key = key } in
Lwt_utils_unix.Socket.connect path >>=? fun conn -> 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 let encoding = result_encoding Public_key.Response.encoding in
Lwt_utils_unix.Socket.recv conn encoding >>=? function Lwt_utils_unix.Socket.recv conn encoding >>=? fun res ->
| Error err -> Lwt.return (Error err) Lwt_unix.close conn >>= fun () ->
| Ok res -> Lwt_unix.close conn >>= fun () -> return res.public_key Lwt.return res
let sign path key data = match path with let sign path pkh data =
| Socket path -> socket_sign path key data match path with
| Socket path -> socket_sign path pkh data
| Https (host, port) -> | Https (host, port) ->
call host port Signer_services.sign { key ; data } >>=? fun res -> RPC_client.call_service
return res.signature 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 let request_public_key path pkh =
| Socket path -> socket_request_public_key path key match path with
| Socket path -> socket_request_public_key path pkh
| Https (host, port) -> | Https (host, port) ->
call host port Signer_services.public_key { key } >>=? fun res -> RPC_client.call_service
return res.public_key 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 module Remote_signer : SIGNER = struct
let scheme = "remote" let scheme = "remote"
@ -70,7 +69,7 @@ module Remote_signer : SIGNER = struct
that get evaluated to default values '$HOME/.tezos-signer-socket', \ that get evaluated to default values '$HOME/.tezos-signer-socket', \
localhost and 6732, and can be set later on." 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 *) (* secret key is the identifier of the location key identifier *)
type secret_key = key_path type secret_key = key_path
@ -84,18 +83,22 @@ module Remote_signer : SIGNER = struct
let path_of_human_input = function let path_of_human_input = function
| "unix" :: key :: [] -> | "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 :: [] -> | "unix" :: file :: key :: [] ->
return (Socket (Unix file), key) return (Socket (Unix file),
Signature.Public_key_hash.of_b58check_exn key)
| "tcp" :: host :: port :: 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 *) (* Temporary FIXME *)
(* | "tcp" :: host :: key :: [] -> *) (* | "tcp" :: host :: key :: [] -> *)
(* return (Socket (Tcp (host, "$TEZOS_SIGNER_TCP_PORT")), key) *) (* return (Socket (Tcp (host, "$TEZOS_SIGNER_TCP_PORT")), key) *)
(* | "tcp" :: key :: [] -> *) (* | "tcp" :: key :: [] -> *)
(* return (Socket (Tcp ("$TEZOS_SIGNER_TCP_HOST", "$TEZOS_SIGNER_TCP_PORT")), key) *) (* return (Socket (Tcp ("$TEZOS_SIGNER_TCP_HOST", "$TEZOS_SIGNER_TCP_PORT")), key) *)
| "https" :: host :: 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 *) (* Temporary FIXME *)
(* | "https" :: host :: key :: [] -> *) (* | "https" :: host :: key :: [] -> *)
(* return (Https (host, "$TEZOS_SIGNER_HTTPS_PORT"), key) *) (* return (Https (host, "$TEZOS_SIGNER_HTTPS_PORT"), key) *)
@ -108,9 +111,9 @@ module Remote_signer : SIGNER = struct
Format.pp_print_text description Format.pp_print_text description
let locator_of_path = function let locator_of_path = function
| Socket (Unix path), key -> [ "unix" ; path ; 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 ; 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 ; 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 = let pk_locator_of_human_input _cctxt path =
path_of_human_input path >>=? fun pk -> path_of_human_input path >>=? fun pk ->

View File

@ -7,7 +7,7 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type error += Unkwnon_alias_key of string type error += Unknown_alias_key of string
let () = let () =
register_error_kind `Permanent register_error_kind `Permanent
@ -17,84 +17,85 @@ let () =
~pp: (fun ppf s -> ~pp: (fun ppf s ->
Format.fprintf ppf "The key %s does not is not known on the remote signer" s) Format.fprintf ppf "The key %s does not is not known on the remote signer" s)
Data_encoding.(obj1 (req "value" string)) Data_encoding.(obj1 (req "value" string))
(function Unkwnon_alias_key s -> Some s | _ -> None) (function Unknown_alias_key s -> Some s | _ -> None)
(fun s -> Unkwnon_alias_key s) (fun s -> Unknown_alias_key s)
type key = string
module Sign = struct module Sign = struct
module Request = struct module Request = struct
type t = { type t = {
key : key ; pkh: Signature.Public_key_hash.t ;
data: MBytes.t ; data: MBytes.t ;
} }
let encoding = let encoding =
let open Data_encoding in let open Data_encoding in
conv conv
(fun { key ; data } -> (fun { pkh ; data } ->
( key, data)) (pkh, data))
(fun (key, data) -> (fun (pkh, data) ->
{ key ; data }) { pkh ; data })
(obj2 (obj2
(req "key" string) (req "pkh" Signature.Public_key_hash.encoding)
(req "data" bytes)) (req "data" bytes))
end end
module Response = struct module Response = struct
type t = {
signature : Signature.t type t = Signature.t
}
let encoding = let encoding =
let open Data_encoding in Data_encoding.(obj1 (req "signature" Signature.encoding))
conv
(fun { signature } -> (signature))
(fun (signature) -> { signature })
(obj1 (req "signature" Signature.encoding))
end end
end end
module Public_key = struct module Public_key = struct
module Request = struct module Request = struct
type t = {
key : key ; type t = Signature.Public_key_hash.t
}
let encoding = let encoding =
let open Data_encoding in Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding))
conv
(fun { key } -> key)
(fun key -> { key })
(obj1 (req "key" string))
end end
module Response = struct module Response = struct
type t = {
public_key : Signature.Public_key.t ; type t = Signature.Public_key.t
}
let encoding = let encoding =
let open Data_encoding in Data_encoding.(obj1 (req "pubkey" Signature.Public_key.encoding))
conv
(fun { public_key } -> public_key)
(fun public_key -> { public_key })
(obj1 (req "pubkey" Signature.Public_key.encoding))
end end
end end
module Request = struct module Request = struct
type t = type t =
| Sign of Sign.Request.t | Sign of Sign.Request.t
| Public_key of Public_key.Request.t | Public_key of Public_key.Request.t
let encoding = let encoding =
let open Data_encoding in let open Data_encoding in
union union [
[ case (Tag 0) (merge_objs (obj1 (req "kind" (constant "sign"))) Sign.Request.encoding) case (Tag 0)
(merge_objs
(obj1 (req "kind" (constant "sign")))
Sign.Request.encoding)
(function Sign req -> Some ((), req) | _ -> None) (function Sign req -> Some ((), req) | _ -> None)
(fun ((), req) -> Sign req) ; (fun ((), req) -> Sign req) ;
case (Tag 1) (merge_objs (obj1 (req "kind" (constant "public_key"))) Public_key.Request.encoding) case (Tag 1)
(merge_objs
(obj1 (req "kind" (constant "public_key")))
Public_key.Request.encoding)
(function Public_key req -> Some ((), req) | _ -> None) (function Public_key req -> Some ((), req) | _ -> None)
(fun ((), req) -> Public_key req) ] (fun ((), req) -> Public_key req) ;
]
end end

View File

@ -7,44 +7,44 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type error += Unkwnon_alias_key of string type error += Unknown_alias_key of string
type key = string
module Sign : sig module Sign : sig
module Request : sig module Request : sig
type t = { type t = {
key : key ; pkh: Signature.Public_key_hash.t ;
data: MBytes.t ; data: MBytes.t ;
} }
val encoding : t Data_encoding.t val encoding : t Data_encoding.t
end end
module Response : sig module Response : sig
type t = { type t = Signature.t
signature : Signature.t ;
}
val encoding : t Data_encoding.t val encoding : t Data_encoding.t
end end
end end
module Public_key : sig module Public_key : sig
module Request : sig module Request : sig
type t = { type t = Signature.Public_key_hash.t
key : key ;
}
val encoding : t Data_encoding.t val encoding : t Data_encoding.t
end end
module Response : sig module Response : sig
type t = { type t = Signature.Public_key.t
public_key : Signature.Public_key.t ;
}
val encoding : t Data_encoding.t val encoding : t Data_encoding.t
end end
end end
module Request : sig module Request : sig
type t = type t =
| Sign of Sign.Request.t | Sign of Sign.Request.t
| Public_key of Public_key.Request.t | Public_key of Public_key.Request.t
val encoding : t Data_encoding.t val encoding : t Data_encoding.t
end end

View File

@ -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" ~description: "Sign a piece of data with a given remote key"
~query: RPC_query.empty ~query: RPC_query.empty
~input: Sign.Request.encoding ~input: Data_encoding.bytes
~output: Sign.Response.encoding ~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
RPC_path.(root / "sign") 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" ~description: "Retrieve the public key of a given remote key"
~query: RPC_query.empty ~query: RPC_query.empty
~input: Public_key.Request.encoding ~output: Data_encoding.(obj1 (req "public_key" Signature.Public_key.encoding))
~output: Public_key.Response.encoding RPC_path.(root /: Signature.Public_key_hash.rpc_arg)
RPC_path.(root / "public_key")

View File

@ -7,10 +7,10 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
open Signer_messages
val sign : 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 : 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