Client, wallet: Change type of location

This commit is contained in:
Pietro 2018-04-12 17:57:08 +02:00 committed by Grégoire Henry
parent cfe82ab7cf
commit 8b9d02eec4
6 changed files with 122 additions and 73 deletions

View File

@ -8,6 +8,7 @@
(**************************************************************************)
type error += Unregistered_key_scheme of string
let () =
register_error_kind `Permanent
~id: "cli.unregistered_key_scheme"
@ -29,19 +30,21 @@ module Public_key_hash = Client_aliases.Alias (struct
let name = "public key hash"
end)
type location = string list
module type LOCATOR = sig
val name : string
type t
val create : scheme:string -> location:string -> t
val create : scheme:string -> location:location -> t
val scheme : t -> string
val location : t -> string
val location : t -> location
val to_string : t -> string
val pp : Format.formatter -> t -> unit
end
type sk_locator = Sk_locator of { scheme : string ; location : string }
type pk_locator = Pk_locator of { scheme : string ; location : string }
type sk_locator = Sk_locator of { scheme : string ; location : location }
type pk_locator = Pk_locator of { scheme : string ; location : location }
module Sk_locator = struct
let name = "secret key"
@ -54,10 +57,10 @@ module Sk_locator = struct
let location (Sk_locator { location }) = location
let to_string (Sk_locator { scheme ; location }) =
scheme ^ ":" ^ location
String.concat "/" ((scheme ^ ":") :: List.map Uri.pct_encode location)
let pp ppf (Sk_locator { scheme ; location }) =
Format.pp_print_string ppf (scheme ^ ":" ^ location)
let pp ppf loc =
Format.pp_print_string ppf (to_string loc)
end
module Pk_locator = struct
@ -71,10 +74,10 @@ module Pk_locator = struct
let location (Pk_locator { location }) = location
let to_string (Pk_locator { scheme ; location }) =
scheme ^ ":" ^ location
String.concat "/" ((scheme ^ ":") :: List.map Uri.pct_encode location)
let pp ppf (Pk_locator { scheme ; location }) =
Format.pp_print_string ppf (scheme ^ ":" ^ location)
let pp ppf loc =
Format.pp_print_string ppf (to_string loc)
end
module type KEY = sig
@ -88,7 +91,7 @@ module Locator (K : KEY) (L : LOCATOR) = struct
let of_unencrypted k =
L.create ~scheme:"unencrypted"
~location:(K.to_b58check k)
~location:[K.to_b58check k]
let of_string s =
match String.index s ':' with
@ -96,9 +99,13 @@ module Locator (K : KEY) (L : LOCATOR) = struct
of_unencrypted (K.of_b58check_exn s)
| i ->
let len = String.length s in
create
~scheme:(String.sub s 0 i)
~location:(String.sub s (i+1) (len-i-1))
let scheme = String.sub s 0 i in
let location =
String.sub s (i+1) (len-i-1) |>
String.split '/' |>
List.map Uri.pct_decode |>
List.filter ((<>) "") in
create ~scheme ~location
let of_source s = return (of_string s)
let to_source t = return (to_string t)
@ -125,8 +132,8 @@ module type SIGNER = sig
val sk_to_locator : secret_key -> sk_locator Lwt.t
val pk_to_locator : public_key -> pk_locator Lwt.t
val neuterize : secret_key -> public_key Lwt.t
val public_key : public_key -> Signature.Public_key.t Lwt.t
val public_key_hash : public_key -> Signature.Public_key_hash.t Lwt.t
val public_key : public_key -> Signature.Public_key.t tzresult Lwt.t
val public_key_hash : public_key -> Signature.Public_key_hash.t tzresult Lwt.t
val sign :
?watermark: Signature.watermark ->
secret_key -> MBytes.t -> Signature.t tzresult Lwt.t
@ -140,7 +147,8 @@ let register_signer signer =
let find_signer_for_key cctxt ~scheme =
match Hashtbl.find signers_table scheme with
| exception Not_found -> fail (Unregistered_key_scheme scheme)
| exception Not_found ->
fail (Unregistered_key_scheme scheme)
| signer, false ->
let module Signer = (val signer : SIGNER) in
Signer.init cctxt >>=? fun () ->
@ -151,11 +159,33 @@ let find_signer_for_key cctxt ~scheme =
let registered_signers () : (string * (module SIGNER)) list =
Hashtbl.fold (fun k (v, _) acc -> (k, v) :: acc) signers_table []
type error += Signature_mismatch of Secret_key_locator.t
let () =
register_error_kind `Permanent
~id: "cli.signature_mismatch"
~title: "Signature mismatch"
~description: "The signer produced an invalid signature"
~pp:
(fun ppf sk ->
Format.fprintf ppf
"The signer for %a produced an invalid signature"
Secret_key_locator.pp sk)
Data_encoding.(obj1 (req "locator" Secret_key_locator.encoding))
(function Signature_mismatch sk -> Some sk | _ -> None)
(fun sk -> Signature_mismatch sk)
let sign ?watermark cctxt ((Sk_locator { scheme }) as skloc) buf =
find_signer_for_key cctxt ~scheme >>=? fun signer ->
let module Signer = (val signer : SIGNER) in
Signer.sk_of_locator skloc >>=? fun t ->
Signer.sign ?watermark t buf
Signer.sign ?watermark t buf >>=? fun signature ->
Signer.neuterize t >>= fun pk ->
Signer.public_key pk >>=? fun pubkey ->
fail_unless
(Signature.check pubkey signature buf)
(Signature_mismatch skloc) >>=? fun () ->
return signature
let append ?watermark cctxt loc buf =
sign ?watermark cctxt loc buf >>|? fun signature ->
@ -241,7 +271,7 @@ let get_key (cctxt : #Client_context.wallet) pkh =
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 ->
Signer.public_key pk >>=? fun pk ->
return (n, pk, sk)
let get_keys (wallet : #Client_context.io_wallet) =
@ -254,7 +284,7 @@ let get_keys (wallet : #Client_context.io_wallet) =
find_signer_for_key wallet ~scheme >>=? fun signer ->
let module Signer = (val signer : SIGNER) in
Signer.pk_of_locator pk >>=? fun pk ->
Signer.public_key pk >>= fun pk ->
Signer.public_key pk >>=? fun pk ->
return (name, pkh, pk, sk)
end >>= function
| Ok r -> Lwt.return (Some r)
@ -277,10 +307,11 @@ let alias_keys cctxt name =
| [] -> return None
| (key_name, pkh) :: tl ->
if key_name = name
then
then begin
Public_key.find_opt cctxt name >>=? fun pkm ->
Secret_key.find_opt cctxt name >>=? fun pks ->
return (Some (pkh, pkm, pks))
end
else find_key tl
in find_key l

View File

@ -9,16 +9,17 @@
(** {2 Location of keys using schemes} *)
type sk_locator = Sk_locator of { scheme : string ; location : string }
type pk_locator = Pk_locator of { scheme : string ; location : string }
type location = string list
type sk_locator = Sk_locator of { scheme : string ; location : location }
type pk_locator = Pk_locator of { scheme : string ; location : location }
module type LOCATOR = sig
val name : string
type t
val create : scheme:string -> location:string -> t
val create : scheme:string -> location:location -> t
val scheme : t -> string
val location : t -> string
val location : t -> location
val to_string : t -> string
val pp : Format.formatter -> t -> unit
end
@ -84,10 +85,10 @@ module type SIGNER = sig
val neuterize : secret_key -> public_key Lwt.t
(** [neuterize sk] is the corresponding [pk]. *)
val public_key : public_key -> Signature.Public_key.t Lwt.t
(** [public_key pk] is the full version of [pk]. *)
val public_key : public_key -> Signature.Public_key.t tzresult Lwt.t
(** [public_key pk] is the Ed25519 version of [pk]. *)
val public_key_hash : public_key -> Signature.Public_key_hash.t Lwt.t
val public_key_hash : public_key -> Signature.Public_key_hash.t tzresult Lwt.t
(** [public_key_hash pk] is the hash of [pk]. *)
val sign :

View File

@ -76,21 +76,24 @@ module Encrypted_signer : SIGNER = struct
if Secret_key_locator.scheme skloc <> scheme then
Lwt.return a
else
let location = Secret_key_locator.location skloc in
match Base58.safe_decode location with
| None -> Lwt.fail Exit
| Some payload ->
let salt, skenc = salt_skenc_of_skloc payload in
match decrypt_sk skenc salt a with
| Some sk ->
Hashtbl.replace decrypted_sks location
(Data_encoding.Binary.of_bytes_exn Signature.Secret_key.encoding sk) ;
Lwt.return a
| None ->
passwd_ask_loop
cctxt ~name ~salt ~skenc >>= fun (passwd, decrypted_sk) ->
Hashtbl.replace decrypted_sks location decrypted_sk ;
Lwt.return (passwd :: a)
match Secret_key_locator.location skloc with
|location :: _ -> begin
match Base58.safe_decode location with
| None -> Lwt.fail Exit
| Some payload ->
let salt, skenc = salt_skenc_of_skloc payload in
match decrypt_sk skenc salt a with
| Some sk ->
Hashtbl.replace decrypted_sks location
(Data_encoding.Binary.of_bytes_exn Signature.Secret_key.encoding sk);
Lwt.return a
| None ->
passwd_ask_loop
cctxt ~name ~salt ~skenc >>= fun (passwd, decrypted_sk) ->
Hashtbl.replace decrypted_sks location decrypted_sk ;
Lwt.return (passwd :: a)
end
|_ -> Lwt.fail Exit
end [] sks
let init cctxt =
@ -117,7 +120,7 @@ module Encrypted_signer : SIGNER = struct
let payload = MBytes.(to_string (concat "" [salt; encrypted_passwd])) in
let location = Base58.safe_encode payload in
Hashtbl.replace decrypted_sks location sk ;
return (Secret_key_locator.create ~scheme ~location)
return (Secret_key_locator.create ~scheme ~location:[location])
let rec get_boolean_answer (cctxt : #Client_context.io_wallet) ~default ~msg =
let prompt = if default then "(Y/n/q)" else "(y/N/q)" in
@ -179,29 +182,36 @@ module Encrypted_signer : SIGNER = struct
let pk_locator_of_human_input _cctxt = function
| [] -> failwith "Missing public key argument."
| pk :: _ -> return (Public_key_locator.create ~scheme ~location:pk)
| pk :: _ -> return (Public_key_locator.create ~scheme ~location:[pk])
let sk_of_locator (Sk_locator { location }) =
match Hashtbl.find decrypted_sks location with
| exception Not_found -> failwith "Unknown secret key location."
| sk -> return sk
let sk_of_locator = function
| (Sk_locator { location = [location] }) -> begin
match Hashtbl.find decrypted_sks location with
| exception Not_found -> failwith "Unknown secret key location."
| sk -> return sk
end
| (Sk_locator { location = _ }) ->
failwith "Wrong location type."
let pk_of_locator (Pk_locator { location }) =
Lwt.return (Signature.Public_key.of_b58check location)
let pk_of_locator = function
|(Pk_locator { location = [location] }) ->
Lwt.return (Signature.Public_key.of_b58check location)
|(Pk_locator { location = _ }) ->
failwith "Wrong location type."
let sk_to_locator sk =
Secret_key_locator.create
~scheme ~location:(Signature.Secret_key.to_b58check sk) |>
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
Lwt.return
let pk_to_locator pk =
Public_key_locator.create
~scheme ~location:(Signature.Public_key.to_b58check pk) |>
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
Lwt.return
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
let public_key x = Lwt.return x
let public_key_hash x = Lwt.return (Signature.Public_key.hash x)
let public_key x = return x
let public_key_hash x = return (Signature.Public_key.hash x)
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
end

View File

@ -30,35 +30,42 @@ module Unencrypted_signer : SIGNER = struct
let sk_locator_of_human_input _cctxt = function
| sk :: _ ->
return (Secret_key_locator.create ~scheme ~location:sk)
return (Secret_key_locator.create ~scheme ~location:[sk])
| [] ->
let _, _, sk = Ed25519.generate_key () in
return (Secret_key_locator.create ~scheme
~location:(Ed25519.Secret_key.to_b58check sk))
~location:[Ed25519.Secret_key.to_b58check sk])
let pk_locator_of_human_input _cctxt = function
| [] -> failwith "Missing public key argument"
| pk :: _ -> return (Public_key_locator.create ~scheme ~location:pk)
| pk :: _ -> return (Public_key_locator.create ~scheme ~location:[pk])
let sk_of_locator (Sk_locator { location }) =
Lwt.return (Signature.Secret_key.of_b58check location)
let sk_of_locator = function
|(Sk_locator { location = ( location :: _ ) }) ->
Lwt.return (Signature.Secret_key.of_b58check location)
|(Sk_locator { location = _ }) ->
failwith "Wrong type of location"
let pk_of_locator (Pk_locator { location }) =
Lwt.return (Signature.Public_key.of_b58check location)
let pk_of_locator = function
|(Pk_locator { location = ( location :: _ ) }) ->
Lwt.return (Signature.Public_key.of_b58check location)
|(Pk_locator { location = _ }) ->
failwith "Wrong type of location"
let sk_to_locator sk =
Secret_key_locator.create
~scheme ~location:(Signature.Secret_key.to_b58check sk) |>
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
Lwt.return
let pk_to_locator pk =
Public_key_locator.create
~scheme ~location:(Signature.Public_key.to_b58check pk) |>
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
Lwt.return
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
let public_key x = Lwt.return x
let public_key_hash x = Lwt.return (Signature.Public_key.hash x)
let public_key x = return x
let public_key_hash x = return (Signature.Public_key.hash x)
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
end

View File

@ -107,7 +107,7 @@ let commands () =
Signer.pk_to_locator pk >>= fun pkloc ->
Public_key.find_opt cctxt name >>=? function
| None ->
Signer.public_key_hash pk >>= fun pkh ->
Signer.public_key_hash pk >>=? fun pkh ->
Secret_key.add ~force cctxt name skloc >>=? fun () ->
Public_key_hash.add ~force cctxt name pkh >>=? fun () ->
Public_key.add ~force cctxt name pkloc
@ -142,7 +142,7 @@ let commands () =
Signer.pk_locator_of_human_input
(cctxt :> Client_context.io_wallet) location >>=? fun pkloc ->
Signer.pk_of_locator pkloc >>=? fun pk ->
Signer.public_key_hash pk >>= fun pkh ->
Signer.public_key_hash pk >>=? fun pkh ->
Public_key_hash.add ~force cctxt name pkh >>=? fun () ->
Public_key.add ~force cctxt name pkloc) ;
@ -192,7 +192,7 @@ let commands () =
find_signer_for_key ~scheme cctxt >>=? fun signer ->
let module Signer = (val signer : SIGNER) in
Signer.pk_of_locator pkloc >>=? fun pk ->
Signer.public_key pk >>= fun pk ->
Signer.public_key pk >>=? fun pk ->
ok_lwt @@ cctxt#message "Public Key: %a"
Signature.Public_key.pp pk >>=? fun () ->
if show_private then

View File

@ -116,7 +116,7 @@ let activate_alpha ?(vote = false) () =
let fitness = Fitness_repr.from_int64 0L in
let dictator_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:"edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6" in
~location:["edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6"] in
let protocol_parameters =
if vote then vote_protocol_parameters else protocol_parameters in
Tezos_client_genesis.Client_proto_main.bake
@ -250,7 +250,7 @@ module Account = struct
~amount () =
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check account.sk) in
~location:[Signature.Secret_key.to_b58check account.sk] in
Client_proto_context.transfer
(new wrap_full (no_write_context !rpc_config ~block))
block
@ -274,7 +274,7 @@ module Account = struct
| Some delegate -> true, Some delegate in
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check src.sk) in
~location:[Signature.Secret_key.to_b58check src.sk] in
Client_proto_context.originate_account
~source:src.contract
~src_pk:src.pk
@ -508,7 +508,7 @@ module Baking = struct
None in
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check contract.sk) in
~location:[Signature.Secret_key.to_b58check contract.sk] in
Client_baking_forge.forge_block
ctxt
block