Signer: explicit registration of signers
instead of toplevel side-effects and `-link-all`
This commit is contained in:
parent
502017c863
commit
0dbe24290f
@ -74,6 +74,12 @@ let main select_commands =
|
|||||||
ignore Clic.(setup_formatter Format.err_formatter
|
ignore Clic.(setup_formatter Format.err_formatter
|
||||||
(if Unix.isatty Unix.stderr then Ansi else Plain) Short) ;
|
(if Unix.isatty Unix.stderr then Ansi else Plain) Short) ;
|
||||||
init_logger () >>= fun () ->
|
init_logger () >>= fun () ->
|
||||||
|
Client_keys.register_signer
|
||||||
|
(module Tezos_signer_backends.Unencrypted) ;
|
||||||
|
Client_keys.register_signer
|
||||||
|
(module Tezos_signer_backends.Encrypted) ;
|
||||||
|
Client_keys.register_signer
|
||||||
|
(module Tezos_signer_backends.Remote) ;
|
||||||
Lwt.catch begin fun () -> begin
|
Lwt.catch begin fun () -> begin
|
||||||
Client_config.parse_config_args
|
Client_config.parse_config_args
|
||||||
(new unix_full
|
(new unix_full
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
tezos-client-commands
|
tezos-client-commands
|
||||||
tezos-stdlib-unix
|
tezos-stdlib-unix
|
||||||
tezos-rpc-http
|
tezos-rpc-http
|
||||||
|
tezos-signer-backends
|
||||||
pbkdf
|
pbkdf
|
||||||
bip39
|
bip39
|
||||||
tezos-shell-services))
|
tezos-shell-services))
|
||||||
|
@ -9,13 +9,12 @@
|
|||||||
|
|
||||||
open Client_keys
|
open Client_keys
|
||||||
|
|
||||||
module Encrypted_signer : SIGNER = struct
|
let scheme = "encrypted"
|
||||||
let scheme = "encrypted"
|
|
||||||
|
|
||||||
let title =
|
let title =
|
||||||
"Built-in signer using encrypted keys."
|
"Built-in signer using encrypted keys."
|
||||||
|
|
||||||
let description =
|
let description =
|
||||||
"If you try to import a secret key without additional argument, you will \
|
"If you try to import a secret key without additional argument, you will \
|
||||||
be asked to either generate a new key, or to import the elements \
|
be asked to either generate a new key, or to import the elements \
|
||||||
from your fundraiser paper wallet.\n\
|
from your fundraiser paper wallet.\n\
|
||||||
@ -24,26 +23,26 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
The format for importing public keys is the raw Base58-encoded \
|
The format for importing public keys is the raw Base58-encoded \
|
||||||
key (starting with 'edpk')."
|
key (starting with 'edpk')."
|
||||||
|
|
||||||
type secret_key = Signature.Secret_key.t
|
type secret_key = Signature.Secret_key.t
|
||||||
type public_key = Signature.Public_key.t
|
type public_key = Signature.Public_key.t
|
||||||
|
|
||||||
(* https://tools.ietf.org/html/rfc2898#section-4.1 *)
|
(* https://tools.ietf.org/html/rfc2898#section-4.1 *)
|
||||||
let salt_len = 8
|
let salt_len = 8
|
||||||
|
|
||||||
(* Fixed zero nonce *)
|
(* Fixed zero nonce *)
|
||||||
let nonce = Crypto_box.zero_nonce
|
let nonce = Crypto_box.zero_nonce
|
||||||
|
|
||||||
(* skloc -> Signature.Secret_key.t *)
|
(* skloc -> Signature.Secret_key.t *)
|
||||||
let decrypted_sks = Hashtbl.create 13
|
let decrypted_sks = Hashtbl.create 13
|
||||||
|
|
||||||
let pbkdf ~salt ~password =
|
let pbkdf ~salt ~password =
|
||||||
let open Cstruct in
|
let open Cstruct in
|
||||||
let salt = of_bigarray salt in
|
let salt = of_bigarray salt in
|
||||||
let password = of_bigarray password in
|
let password = of_bigarray password in
|
||||||
to_bigarray
|
to_bigarray
|
||||||
(Pbkdf.pbkdf2 ~prf:`SHA512 ~count:2048 ~dk_len:32l ~salt ~password)
|
(Pbkdf.pbkdf2 ~prf:`SHA512 ~count:2048 ~dk_len:32l ~salt ~password)
|
||||||
|
|
||||||
let rec decrypt_sk sk salt = function
|
let rec decrypt_sk sk salt = function
|
||||||
| [] -> None
|
| [] -> None
|
||||||
| password :: pws ->
|
| password :: pws ->
|
||||||
let key = Crypto_box.Secretbox.unsafe_of_bytes (pbkdf ~password ~salt) in
|
let key = Crypto_box.Secretbox.unsafe_of_bytes (pbkdf ~password ~salt) in
|
||||||
@ -51,7 +50,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
| None -> decrypt_sk sk salt pws
|
| None -> decrypt_sk sk salt pws
|
||||||
| Some sk -> Some sk
|
| Some sk -> Some sk
|
||||||
|
|
||||||
let salt_skenc_of_skloc skloc =
|
let salt_skenc_of_skloc skloc =
|
||||||
let open Cstruct in
|
let open Cstruct in
|
||||||
let skloc = of_string skloc in
|
let skloc = of_string skloc in
|
||||||
let len = len skloc in
|
let len = len skloc in
|
||||||
@ -59,7 +58,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
let skenc = sub skloc salt_len (len - salt_len) in
|
let skenc = sub skloc salt_len (len - salt_len) in
|
||||||
to_bigarray salt, to_bigarray skenc
|
to_bigarray salt, to_bigarray skenc
|
||||||
|
|
||||||
let rec passwd_ask_loop (cctxt : #Client_context.io_wallet) ~name ~salt ~skenc =
|
let rec passwd_ask_loop (cctxt : #Client_context.io_wallet) ~name ~salt ~skenc =
|
||||||
cctxt#prompt_password "Enter password for encrypted key %s: " name >>=? fun password ->
|
cctxt#prompt_password "Enter password for encrypted key %s: " name >>=? fun password ->
|
||||||
let key = pbkdf ~salt ~password in
|
let key = pbkdf ~salt ~password in
|
||||||
let key = Crypto_box.Secretbox.unsafe_of_bytes key in
|
let key = Crypto_box.Secretbox.unsafe_of_bytes key in
|
||||||
@ -70,7 +69,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
Signature.Secret_key.encoding
|
Signature.Secret_key.encoding
|
||||||
decrypted_sk))
|
decrypted_sk))
|
||||||
|
|
||||||
let ask_all_passwords (cctxt : #Client_context.io_wallet) sks =
|
let ask_all_passwords (cctxt : #Client_context.io_wallet) sks =
|
||||||
fold_left_s begin fun a (name, skloc) ->
|
fold_left_s begin fun a (name, skloc) ->
|
||||||
if Secret_key_locator.scheme skloc <> scheme then
|
if Secret_key_locator.scheme skloc <> scheme then
|
||||||
return a
|
return a
|
||||||
@ -95,21 +94,21 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
|_ -> Lwt.fail Exit
|
|_ -> Lwt.fail Exit
|
||||||
end [] sks
|
end [] sks
|
||||||
|
|
||||||
let init cctxt =
|
let init cctxt =
|
||||||
Secret_key.load cctxt >>=? fun sks ->
|
Secret_key.load cctxt >>=? fun sks ->
|
||||||
Lwt.try_bind
|
Lwt.try_bind
|
||||||
(fun () -> ask_all_passwords cctxt sks)
|
(fun () -> ask_all_passwords cctxt sks)
|
||||||
(fun _ -> return ())
|
(fun _ -> return ())
|
||||||
(fun _ -> failwith "Corrupted secret key database. Aborting.")
|
(fun _ -> failwith "Corrupted secret key database. Aborting.")
|
||||||
|
|
||||||
let input_new_passphrase (cctxt : #Client_context.io_wallet) =
|
let input_new_passphrase (cctxt : #Client_context.io_wallet) =
|
||||||
cctxt#prompt_password "Enter passphrase to encrypt your key: " >>=? fun password ->
|
cctxt#prompt_password "Enter passphrase to encrypt your key: " >>=? fun password ->
|
||||||
cctxt#prompt_password "Confirm passphrase: " >>=? fun confirm ->
|
cctxt#prompt_password "Confirm passphrase: " >>=? fun confirm ->
|
||||||
if password <> confirm then
|
if password <> confirm then
|
||||||
failwith "Passphrases do not match."
|
failwith "Passphrases do not match."
|
||||||
else return password
|
else return password
|
||||||
|
|
||||||
let encrypt_sk cctxt sk =
|
let encrypt_sk cctxt sk =
|
||||||
input_new_passphrase cctxt >>=? fun password ->
|
input_new_passphrase cctxt >>=? fun password ->
|
||||||
let salt = Rand.generate salt_len in
|
let salt = Rand.generate salt_len in
|
||||||
let key = Crypto_box.Secretbox.unsafe_of_bytes (pbkdf ~password ~salt) in
|
let key = Crypto_box.Secretbox.unsafe_of_bytes (pbkdf ~password ~salt) in
|
||||||
@ -120,7 +119,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
Hashtbl.replace decrypted_sks location sk ;
|
Hashtbl.replace decrypted_sks location sk ;
|
||||||
return (Secret_key_locator.create ~scheme ~location:[location])
|
return (Secret_key_locator.create ~scheme ~location:[location])
|
||||||
|
|
||||||
let rec get_boolean_answer (cctxt : #Client_context.io_wallet) ~default ~msg =
|
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
|
let prompt = if default then "(Y/n/q)" else "(y/N/q)" in
|
||||||
cctxt#prompt "%s %s: " msg prompt >>=? fun gen ->
|
cctxt#prompt "%s %s: " msg prompt >>=? fun gen ->
|
||||||
match default, String.lowercase_ascii gen with
|
match default, String.lowercase_ascii gen with
|
||||||
@ -130,7 +129,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
| _, "q" -> failwith "Exit by user request."
|
| _, "q" -> failwith "Exit by user request."
|
||||||
| _ -> get_boolean_answer cctxt ~msg ~default
|
| _ -> get_boolean_answer cctxt ~msg ~default
|
||||||
|
|
||||||
let rec sk_of_mnemonic (cctxt : #Client_context.io_wallet) =
|
let rec sk_of_mnemonic (cctxt : #Client_context.io_wallet) =
|
||||||
cctxt#prompt "Enter the e-mail used for the paper wallet: " >>=? fun email ->
|
cctxt#prompt "Enter the e-mail used for the paper wallet: " >>=? fun email ->
|
||||||
let rec loop_words acc i =
|
let rec loop_words acc i =
|
||||||
if i > 14 then return (List.rev acc) else
|
if i > 14 then return (List.rev acc) else
|
||||||
@ -159,7 +158,7 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
| true -> return sk
|
| true -> return sk
|
||||||
| false -> sk_of_mnemonic cctxt
|
| false -> sk_of_mnemonic cctxt
|
||||||
|
|
||||||
let sk_locator_of_human_input cctxt = function
|
let sk_locator_of_human_input cctxt = function
|
||||||
| sk :: _ ->
|
| sk :: _ ->
|
||||||
Lwt.return (Signature.Secret_key.of_b58check sk) >>=? fun sk ->
|
Lwt.return (Signature.Secret_key.of_b58check sk) >>=? fun sk ->
|
||||||
encrypt_sk cctxt sk
|
encrypt_sk cctxt sk
|
||||||
@ -178,11 +177,11 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
encrypt_sk cctxt sk
|
encrypt_sk cctxt sk
|
||||||
end
|
end
|
||||||
|
|
||||||
let pk_locator_of_human_input _cctxt = function
|
let pk_locator_of_human_input _cctxt = function
|
||||||
| [] -> failwith "Missing public key argument."
|
| [] -> 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 = function
|
let sk_of_locator = function
|
||||||
| (Sk_locator { location = [location] }) -> begin
|
| (Sk_locator { location = [location] }) -> begin
|
||||||
match Hashtbl.find decrypted_sks location with
|
match Hashtbl.find decrypted_sks location with
|
||||||
| exception Not_found -> failwith "Unknown secret key location."
|
| exception Not_found -> failwith "Unknown secret key location."
|
||||||
@ -191,27 +190,23 @@ module Encrypted_signer : SIGNER = struct
|
|||||||
| (Sk_locator { location = _ }) ->
|
| (Sk_locator { location = _ }) ->
|
||||||
failwith "Wrong location type."
|
failwith "Wrong location type."
|
||||||
|
|
||||||
let pk_of_locator = function
|
let pk_of_locator = function
|
||||||
|(Pk_locator { location = [location] }) ->
|
|(Pk_locator { location = [location] }) ->
|
||||||
Lwt.return (Signature.Public_key.of_b58check location)
|
Lwt.return (Signature.Public_key.of_b58check location)
|
||||||
|(Pk_locator { location = _ }) ->
|
|(Pk_locator { location = _ }) ->
|
||||||
failwith "Wrong location type."
|
failwith "Wrong location type."
|
||||||
|
|
||||||
let sk_to_locator sk =
|
let sk_to_locator sk =
|
||||||
Secret_key_locator.create
|
Secret_key_locator.create
|
||||||
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
|
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
|
||||||
Lwt.return
|
Lwt.return
|
||||||
|
|
||||||
let pk_to_locator pk =
|
let pk_to_locator pk =
|
||||||
Public_key_locator.create
|
Public_key_locator.create
|
||||||
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
|
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
|
||||||
Lwt.return
|
Lwt.return
|
||||||
|
|
||||||
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
|
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
|
||||||
let public_key x = return x
|
let public_key x = return x
|
||||||
let public_key_hash x = return (Signature.Public_key.hash x)
|
let public_key_hash x = return (Signature.Public_key.hash x)
|
||||||
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
|
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
|
||||||
end
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_signer (module Encrypted_signer)
|
|
||||||
|
10
src/lib_signer_backends/encrypted.mli
Normal file
10
src/lib_signer_backends/encrypted.mli
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2017. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
include Client_keys.SIGNER
|
@ -15,7 +15,7 @@
|
|||||||
-open Tezos_client_base
|
-open Tezos_client_base
|
||||||
-open Tezos_signer_services
|
-open Tezos_signer_services
|
||||||
-open Tezos_rpc_http
|
-open Tezos_rpc_http
|
||||||
-linkall -w -9))))
|
-w -9))))
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
((name runtest_indent)
|
((name runtest_indent)
|
||||||
|
@ -166,5 +166,4 @@ module Remote_signer : SIGNER = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let () =
|
include Remote_signer
|
||||||
register_signer (module Remote_signer)
|
|
||||||
|
10
src/lib_signer_backends/remote.mli
Normal file
10
src/lib_signer_backends/remote.mli
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2017. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
include Client_keys.SIGNER
|
@ -9,13 +9,12 @@
|
|||||||
|
|
||||||
open Client_keys
|
open Client_keys
|
||||||
|
|
||||||
module Unencrypted_signer : SIGNER = struct
|
let scheme = "unencrypted"
|
||||||
let scheme = "unencrypted"
|
|
||||||
|
|
||||||
let title =
|
let title =
|
||||||
"Built-in signer using raw unencrypted keys."
|
"Built-in signer using raw unencrypted keys."
|
||||||
|
|
||||||
let description =
|
let description =
|
||||||
"Do not use this signer except for playing on the test chain.\n\
|
"Do not use this signer except for playing on the test chain.\n\
|
||||||
The format for importing secret keys is either no argument (will \
|
The format for importing secret keys is either no argument (will \
|
||||||
generate a key) or the raw Base58-encoded key (starting with \
|
generate a key) or the raw Base58-encoded key (starting with \
|
||||||
@ -23,12 +22,12 @@ module Unencrypted_signer : SIGNER = struct
|
|||||||
The format for importing public keys is the raw Base58-encoded \
|
The format for importing public keys is the raw Base58-encoded \
|
||||||
key (starting with 'edpk')."
|
key (starting with 'edpk')."
|
||||||
|
|
||||||
type secret_key = Signature.Secret_key.t
|
type secret_key = Signature.Secret_key.t
|
||||||
type public_key = Signature.Public_key.t
|
type public_key = Signature.Public_key.t
|
||||||
|
|
||||||
let init _wallet = return ()
|
let init _wallet = return ()
|
||||||
|
|
||||||
let sk_locator_of_human_input _cctxt = function
|
let sk_locator_of_human_input _cctxt = function
|
||||||
| sk :: _ ->
|
| sk :: _ ->
|
||||||
return (Secret_key_locator.create ~scheme ~location:[sk])
|
return (Secret_key_locator.create ~scheme ~location:[sk])
|
||||||
| [] ->
|
| [] ->
|
||||||
@ -36,38 +35,34 @@ module Unencrypted_signer : SIGNER = struct
|
|||||||
return (Secret_key_locator.create ~scheme
|
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
|
let pk_locator_of_human_input _cctxt = function
|
||||||
| [] -> failwith "Missing public key argument"
|
| [] -> 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 = function
|
let sk_of_locator = function
|
||||||
|(Sk_locator { location = ( location :: _ ) }) ->
|
|(Sk_locator { location = ( location :: _ ) }) ->
|
||||||
Lwt.return (Signature.Secret_key.of_b58check location)
|
Lwt.return (Signature.Secret_key.of_b58check location)
|
||||||
|(Sk_locator { location = _ }) ->
|
|(Sk_locator { location = _ }) ->
|
||||||
failwith "Wrong type of location"
|
failwith "Wrong type of location"
|
||||||
|
|
||||||
|
|
||||||
let pk_of_locator = function
|
let pk_of_locator = function
|
||||||
|(Pk_locator { location = ( location :: _ ) }) ->
|
|(Pk_locator { location = ( location :: _ ) }) ->
|
||||||
Lwt.return (Signature.Public_key.of_b58check location)
|
Lwt.return (Signature.Public_key.of_b58check location)
|
||||||
|(Pk_locator { location = _ }) ->
|
|(Pk_locator { location = _ }) ->
|
||||||
failwith "Wrong type of location"
|
failwith "Wrong type of location"
|
||||||
|
|
||||||
let sk_to_locator sk =
|
let sk_to_locator sk =
|
||||||
Secret_key_locator.create
|
Secret_key_locator.create
|
||||||
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
|
~scheme ~location:[Signature.Secret_key.to_b58check sk] |>
|
||||||
Lwt.return
|
Lwt.return
|
||||||
|
|
||||||
let pk_to_locator pk =
|
let pk_to_locator pk =
|
||||||
Public_key_locator.create
|
Public_key_locator.create
|
||||||
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
|
~scheme ~location:[Signature.Public_key.to_b58check pk] |>
|
||||||
Lwt.return
|
Lwt.return
|
||||||
|
|
||||||
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
|
let neuterize x = Lwt.return (Signature.Secret_key.to_public_key x)
|
||||||
let public_key x = return x
|
let public_key x = return x
|
||||||
let public_key_hash x = return (Signature.Public_key.hash x)
|
let public_key_hash x = return (Signature.Public_key.hash x)
|
||||||
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
|
let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
|
||||||
end
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_signer (module Unencrypted_signer)
|
|
||||||
|
10
src/lib_signer_backends/unencrypted.mli
Normal file
10
src/lib_signer_backends/unencrypted.mli
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2017. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
include Client_keys.SIGNER
|
@ -616,3 +616,7 @@ let display_level block =
|
|||||||
|
|
||||||
let endorsement_security_deposit block =
|
let endorsement_security_deposit block =
|
||||||
Constants_services.endorsement_security_deposit !rpc_ctxt block
|
Constants_services.endorsement_security_deposit !rpc_ctxt block
|
||||||
|
|
||||||
|
let () =
|
||||||
|
Client_keys.register_signer
|
||||||
|
(module Tezos_signer_backends.Unencrypted)
|
||||||
|
Loading…
Reference in New Issue
Block a user