ligo/src/client/client_keys.ml

131 lines
5.4 KiB
OCaml
Raw Normal View History

2016-09-08 21:13:10 +04:00
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2016. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
module Ed25519 = Environment.Ed25519
2016-09-08 21:13:10 +04:00
module Public_key_hash = Client_aliases.Alias (struct
type t = Ed25519.Public_key_hash.t
let encoding = Ed25519.Public_key_hash.encoding
let of_source _ s = Lwt.return (Ed25519.Public_key_hash.of_b48check s)
let to_source _ p = Lwt.return (Ed25519.Public_key_hash.to_b48check p)
2016-09-08 21:13:10 +04:00
let name = "public key hash"
end)
module Public_key = Client_aliases.Alias (struct
type t = Ed25519.public_key
let encoding = Ed25519.public_key_encoding
let of_source _ s =
2016-09-08 21:13:10 +04:00
Lwt.return (Sodium.Sign.Bytes.to_public_key
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
let to_source _ p =
2016-09-08 21:13:10 +04:00
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
(Bytes.to_string (Sodium.Sign.Bytes.of_public_key p)))
let name = "public key"
end)
module Secret_key = Client_aliases.Alias (struct
type t = Ed25519.secret_key
let encoding = Ed25519.secret_key_encoding
let of_source _ s =
2016-09-08 21:13:10 +04:00
Lwt.return (Sodium.Sign.Bytes.to_secret_key
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
let to_source _ p =
2016-09-08 21:13:10 +04:00
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
(Bytes.to_string (Sodium.Sign.Bytes.of_secret_key p)))
let name = "secret key"
end)
let gen_keys cctxt name =
2016-09-08 21:13:10 +04:00
let secret_key, public_key = Sodium.Sign.random_keypair () in
Secret_key.add cctxt name secret_key >>= fun () ->
Public_key.add cctxt name public_key >>= fun () ->
Public_key_hash.add cctxt name (Ed25519.hash public_key) >>= fun () ->
cctxt.message "I generated a brand new pair of keys under the name '%s'." name
2016-09-08 21:13:10 +04:00
let check_keys_consistency pk sk =
let message = MBytes.of_string "Voulez-vous coucher avec moi, ce soir ?" in
let signature = Ed25519.sign sk message in
Ed25519.check_signature pk signature message
let get_key cctxt pkh =
Public_key_hash.rev_find cctxt pkh >>= function
| None -> cctxt.error "no keys for the source contract manager"
2016-09-08 21:13:10 +04:00
| Some n ->
Public_key.find cctxt n >>= fun pk ->
Secret_key.find cctxt n >>= fun sk ->
2016-09-08 21:13:10 +04:00
return (n, pk, sk)
let group =
{ Cli_entries.name = "keys" ;
title = "Commands for managing cryptographic keys" }
2016-09-08 21:13:10 +04:00
let commands () =
let open Cli_entries in
[ command ~group ~desc: "generate a pair of keys"
2016-09-08 21:13:10 +04:00
(prefixes [ "gen" ; "keys" ]
@@ Secret_key.fresh_alias_param
@@ stop)
(fun name cctxt -> gen_keys cctxt name) ;
command ~group ~desc: "add a secret key to the wallet"
2016-09-08 21:13:10 +04:00
(prefixes [ "add" ; "secret" ; "key" ]
@@ Secret_key.fresh_alias_param
@@ Secret_key.source_param
@@ stop)
(fun name sk cctxt ->
2016-09-08 21:13:10 +04:00
Lwt.catch (fun () ->
Public_key.find cctxt name >>= fun pk ->
2016-09-08 21:13:10 +04:00
if check_keys_consistency pk sk || Client_config.force#get then
Secret_key.add cctxt name sk
2016-09-08 21:13:10 +04:00
else
cctxt.error
"public and secret keys '%s' don't correspond, \
please don't use -force true" name)
2016-09-08 21:13:10 +04:00
(function
| Not_found ->
cctxt.error
"no public key named '%s', add it before adding the secret key" name
2016-09-08 21:13:10 +04:00
| exn -> Lwt.fail exn)) ;
command ~group ~desc: "add a public key to the wallet"
2016-09-08 21:13:10 +04:00
(prefixes [ "add" ; "public" ; "key" ]
@@ Public_key.fresh_alias_param
@@ Public_key.source_param
@@ stop)
(fun name key cctxt ->
Public_key_hash.add cctxt name (Ed25519.hash key) >>= fun () ->
Public_key.add cctxt name key) ;
command ~group ~desc: "add an ID a public key hash to the wallet"
2016-09-08 21:13:10 +04:00
(prefixes [ "add" ; "identity" ]
@@ Public_key_hash.fresh_alias_param
@@ Public_key_hash.source_param
@@ stop)
(fun name hash cctxt ->
Public_key_hash.add cctxt name hash) ;
command ~group ~desc: "list all public key hashes and associated keys"
2016-09-08 21:13:10 +04:00
(fixed [ "list" ; "known" ; "identities" ])
(fun cctxt ->
Public_key_hash.load cctxt >>= fun l ->
2016-09-08 21:13:10 +04:00
Lwt_list.iter_s (fun (name, pkh) ->
Public_key.mem cctxt name >>= fun pkm ->
Secret_key.mem cctxt name >>= fun pks ->
Public_key_hash.to_source cctxt pkh >>= fun v ->
cctxt.message "%s: %s%s%s" name v
2016-09-08 21:13:10 +04:00
(if pkm then " (public key known)" else "")
(if pks then " (secret key known)" else ""))
2016-09-08 21:13:10 +04:00
l) ;
command ~group ~desc: "forget all keys"
2016-09-08 21:13:10 +04:00
(fixed [ "forget" ; "all" ; "keys" ])
(fun cctxt ->
2016-09-08 21:13:10 +04:00
if not Client_config.force#get then
cctxt.Client_commands.error "this can only used with option -force true"
2016-09-08 21:13:10 +04:00
else
Public_key.save cctxt [] >>= fun () ->
Secret_key.save cctxt [] >>= fun () ->
Public_key_hash.save cctxt []) ;
2016-09-08 21:13:10 +04:00
]