Signer: added deterministic nonces
This commit is contained in:
parent
987d3a9c6a
commit
fd9694d8b0
@ -116,6 +116,22 @@ let check_magic_byte magic_bytes data =
|
||||
else
|
||||
failwith "magic byte 0x%02X not allowed" byte
|
||||
|
||||
|
||||
let check_authorization cctxt pkh data require_auth signature =
|
||||
match require_auth, signature with
|
||||
| false, _ -> return_unit
|
||||
| true, None -> failwith "missing authentication signature field"
|
||||
| true, Some signature ->
|
||||
let to_sign = Signer_messages.Sign.Request.to_sign ~pkh ~data in
|
||||
Authorized_key.load cctxt >>=? fun keys ->
|
||||
if List.fold_left
|
||||
(fun acc (_, key) -> acc || Signature.check key signature to_sign)
|
||||
false keys
|
||||
then
|
||||
return_unit
|
||||
else
|
||||
failwith "invalid authentication signature"
|
||||
|
||||
let sign
|
||||
(cctxt : #Client_context.wallet)
|
||||
Signer_messages.Sign.Request.{ pkh ; data ; signature }
|
||||
@ -127,20 +143,7 @@ let sign
|
||||
-% a Signature.Public_key_hash.Logging.tag pkh
|
||||
-% s magic_byte (MBytes.get_uint8 data 0)) >>= fun () ->
|
||||
check_magic_byte magic_bytes data >>=? fun () ->
|
||||
begin match require_auth, signature with
|
||||
| false, _ -> return_unit
|
||||
| true, None -> failwith "missing authentication signature field"
|
||||
| true, Some signature ->
|
||||
let to_sign = Signer_messages.Sign.Request.to_sign ~pkh ~data in
|
||||
Authorized_key.load cctxt >>=? fun keys ->
|
||||
if List.fold_left
|
||||
(fun acc (_, key) -> acc || Signature.check key signature to_sign)
|
||||
false keys
|
||||
then
|
||||
return_unit
|
||||
else
|
||||
failwith "invalid authentication signature"
|
||||
end >>=? fun () ->
|
||||
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Signing data for key %s"
|
||||
@ -152,6 +155,40 @@ let sign
|
||||
else
|
||||
sign data
|
||||
|
||||
let deterministic_nonce
|
||||
(cctxt : #Client_context.wallet)
|
||||
Signer_messages.Deterministic_nonce.Request.{ pkh ; data ; signature }
|
||||
~require_auth =
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Request for creating a nonce from %d input bytes for key %a"
|
||||
-% t event "request_for_deterministic_nonce"
|
||||
-% s num_bytes (MBytes.length data)
|
||||
-% a Signature.Public_key_hash.Logging.tag pkh) >>= fun () ->
|
||||
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Creating nonce for key %s"
|
||||
-% t event "creating_nonce"
|
||||
-% s Client_keys.Logging.tag name) >>= fun () ->
|
||||
Client_keys.deterministic_nonce sk_uri data
|
||||
|
||||
let deterministic_nonce_hash
|
||||
(cctxt : #Client_context.wallet)
|
||||
Signer_messages.Deterministic_nonce_hash.Request.{ pkh ; data ; signature }
|
||||
~require_auth =
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Request for creating a nonce hash from %d input bytes for key %a"
|
||||
-% t event "request_for_deterministic_nonce_hash"
|
||||
-% s num_bytes (MBytes.length data)
|
||||
-% a Signature.Public_key_hash.Logging.tag pkh) >>= fun () ->
|
||||
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Creating nonce hash for key %s"
|
||||
-% t event "creating_nonce_hash"
|
||||
-% s Client_keys.Logging.tag name) >>= fun () ->
|
||||
Client_keys.deterministic_nonce_hash sk_uri data
|
||||
|
||||
let public_key (cctxt : #Client_context.wallet) pkh =
|
||||
log Tag.DSL.(fun f ->
|
||||
f "Request for public key %a"
|
||||
|
@ -40,3 +40,18 @@ val sign :
|
||||
check_high_watermark:bool -> require_auth:bool -> Signature.t tzresult Lwt.t
|
||||
(** [sign cctxt req ?magic_bytes ~check_high_watermark ~require_auth]
|
||||
signs [req] and returns a signature. *)
|
||||
|
||||
val deterministic_nonce :
|
||||
#Client_context.wallet ->
|
||||
Signer_messages.Deterministic_nonce.Request.t ->
|
||||
require_auth:bool -> MBytes.t tzresult Lwt.t
|
||||
(** [deterministic_nonce cctxt req ~require_auth] generates
|
||||
deterministically a nonce from [req.data]. *)
|
||||
|
||||
val deterministic_nonce_hash :
|
||||
#Client_context.wallet ->
|
||||
Signer_messages.Deterministic_nonce_hash.Request.t ->
|
||||
require_auth:bool -> MBytes.t tzresult Lwt.t
|
||||
(** [deterministic_nonce_hash cctxt req ~require_auth] generates
|
||||
deterministically a nonce from [req.data] and returns the hash of
|
||||
this nonce. *)
|
||||
|
@ -224,7 +224,7 @@ let commands base_dir require_auth =
|
||||
(prefixes [ "launch" ; "https" ; "signer" ] @@
|
||||
param
|
||||
~name:"cert"
|
||||
~desc: "path to th TLS certificate"
|
||||
~desc: "path to the TLS certificate"
|
||||
(parameter (fun _ s ->
|
||||
if not (Sys.file_exists s) then
|
||||
failwith "No such TLS certificate file %s" s
|
||||
@ -232,7 +232,7 @@ let commands base_dir require_auth =
|
||||
return s)) @@
|
||||
param
|
||||
~name:"key"
|
||||
~desc: "path to th TLS key"
|
||||
~desc: "path to the TLS key"
|
||||
(parameter (fun _ s ->
|
||||
if not (Sys.file_exists s) then
|
||||
failwith "No such TLS key file %s" s
|
||||
|
@ -36,6 +36,18 @@ let handle_client ?magic_bytes ~check_high_watermark ~require_auth cctxt fd =
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return_unit
|
||||
| Deterministic_nonce req ->
|
||||
let encoding = result_encoding Deterministic_nonce.Response.encoding in
|
||||
Handler.deterministic_nonce cctxt req ~require_auth >>= fun res ->
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return_unit
|
||||
| Deterministic_nonce_hash req ->
|
||||
let encoding = result_encoding Deterministic_nonce_hash.Response.encoding in
|
||||
Handler.deterministic_nonce_hash cctxt req ~require_auth >>= fun res ->
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return_unit
|
||||
| Public_key pkh ->
|
||||
let encoding = result_encoding Public_key.Response.encoding in
|
||||
Handler.public_key cctxt pkh >>= fun res ->
|
||||
|
@ -153,6 +153,8 @@ module type SIGNER = sig
|
||||
val sign :
|
||||
?watermark: Signature.watermark ->
|
||||
sk_uri -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val deterministic_nonce : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
val deterministic_nonce_hash : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
end
|
||||
|
||||
let signers_table : (string, (module SIGNER)) Hashtbl.t = Hashtbl.create 13
|
||||
@ -232,6 +234,18 @@ let check ?watermark pk_uri signature buf =
|
||||
public_key pk_uri >>=? fun pk ->
|
||||
return (Signature.check ?watermark pk signature buf)
|
||||
|
||||
let deterministic_nonce sk_uri data =
|
||||
let scheme = Option.unopt ~default:"" (Uri.scheme sk_uri) in
|
||||
find_signer_for_key ~scheme >>=? fun signer ->
|
||||
let module Signer = (val signer : SIGNER) in
|
||||
Signer.deterministic_nonce sk_uri data
|
||||
|
||||
let deterministic_nonce_hash sk_uri data =
|
||||
let scheme = Option.unopt ~default:"" (Uri.scheme sk_uri) in
|
||||
find_signer_for_key ~scheme >>=? fun signer ->
|
||||
let module Signer = (val signer : SIGNER) in
|
||||
Signer.deterministic_nonce_hash sk_uri data
|
||||
|
||||
let register_key cctxt ?(force=false) (public_key_hash, pk_uri, sk_uri) ?public_key name =
|
||||
Public_key.add ~force cctxt name (pk_uri, public_key) >>=? fun () ->
|
||||
Secret_key.add ~force cctxt name sk_uri >>=? fun () ->
|
||||
|
@ -70,7 +70,7 @@ module type SIGNER = sig
|
||||
val public_key :
|
||||
?interactive: Client_context.io_wallet ->
|
||||
pk_uri -> Signature.Public_key.t tzresult Lwt.t
|
||||
(** [public_key pk] is the Ed25519 version of [pk].
|
||||
(** [public_key pk] is the Ed25519 version of [pk].
|
||||
|
||||
Some signer implementations improve long-term security by
|
||||
requiring human/manual validation while importing keys, the
|
||||
@ -90,9 +90,18 @@ module type SIGNER = sig
|
||||
val sign :
|
||||
?watermark: Signature.watermark ->
|
||||
sk_uri -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
(** [sign ?watermark sk data] is signature obtained by signing [data] with
|
||||
(** [sign ?watermark sk data] is signature obtained by signing [data] with
|
||||
[sk]. *)
|
||||
|
||||
val deterministic_nonce :
|
||||
sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
(** [deterministic_nonce sk data] is a nonce obtained
|
||||
deterministically from [data] and [sk]. *)
|
||||
|
||||
val deterministic_nonce_hash :
|
||||
sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
(** [deterministic_nonce_hash sk data] is a nonce hash obtained
|
||||
deterministically from [data] and [sk]. *)
|
||||
end
|
||||
|
||||
val register_signer : (module SIGNER) -> unit
|
||||
@ -125,6 +134,12 @@ val check :
|
||||
?watermark:Signature.watermark ->
|
||||
pk_uri -> Signature.t -> MBytes.t -> bool tzresult Lwt.t
|
||||
|
||||
val deterministic_nonce :
|
||||
sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
|
||||
val deterministic_nonce_hash :
|
||||
sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||
|
||||
val register_key :
|
||||
#Client_context.wallet ->
|
||||
?force:bool ->
|
||||
@ -160,4 +175,3 @@ val force_switch : unit -> (bool, 'ctx) Clic.arg
|
||||
|
||||
val make_pk_uri : Uri.t -> pk_uri
|
||||
val make_sk_uri : Uri.t -> sk_uri
|
||||
|
||||
|
@ -343,6 +343,14 @@ let generate_key ?seed () =
|
||||
let pk = Sign.neuterize sk in
|
||||
Public_key.hash pk, pk, sk
|
||||
|
||||
|
||||
let deterministic_nonce sk msg =
|
||||
Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||
|
||||
let deterministic_nonce_hash sk msg =
|
||||
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||
|
||||
|
||||
include Compare.Make(struct
|
||||
type nonrec t = t
|
||||
let compare = MBytes.compare
|
||||
|
@ -282,6 +282,13 @@ let generate_key ?(seed=Rand.generate 32) () =
|
||||
let pkh = Public_key.hash pk in
|
||||
pkh, pk, sk
|
||||
|
||||
let deterministic_nonce sk msg =
|
||||
Hacl.Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||
|
||||
let deterministic_nonce_hash sk msg =
|
||||
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||
|
||||
|
||||
include Compare.Make(struct
|
||||
type nonrec t = t
|
||||
let compare = MBytes.compare
|
||||
|
@ -247,4 +247,8 @@ module type SIGNATURE = sig
|
||||
|
||||
val generate_key: ?seed:MBytes.t -> unit -> (Public_key_hash.t * Public_key.t * Secret_key.t)
|
||||
|
||||
val deterministic_nonce: Secret_key.t -> MBytes.t -> MBytes.t
|
||||
|
||||
val deterministic_nonce_hash: Secret_key.t -> MBytes.t -> MBytes.t
|
||||
|
||||
end
|
||||
|
@ -285,3 +285,9 @@ let generate_key ?(seed=Rand.generate 32) () =
|
||||
let pk = Key.neuterize_exn context sk in
|
||||
let pkh = Public_key.hash pk in
|
||||
pkh, pk, sk
|
||||
|
||||
let deterministic_nonce sk msg =
|
||||
Hacl.Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||
|
||||
let deterministic_nonce_hash sk msg =
|
||||
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||
|
@ -601,3 +601,15 @@ let generate_key ?(algo = Ed25519) ?seed () =
|
||||
let pkh, pk, sk = P256.generate_key ?seed () in
|
||||
(Public_key_hash.P256 pkh,
|
||||
Public_key.P256 pk, Secret_key.P256 sk)
|
||||
|
||||
let deterministic_nonce sk msg =
|
||||
match sk with
|
||||
| Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg
|
||||
| Secret_key.Secp256k1 sk -> Secp256k1.deterministic_nonce sk msg
|
||||
| Secret_key.P256 sk -> P256.deterministic_nonce sk msg
|
||||
|
||||
let deterministic_nonce_hash sk msg =
|
||||
match sk with
|
||||
| Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce_hash sk msg
|
||||
| Secret_key.Secp256k1 sk -> Secp256k1.deterministic_nonce_hash sk msg
|
||||
| Secret_key.P256 sk -> P256.deterministic_nonce_hash sk msg
|
||||
|
@ -262,12 +262,23 @@ module Make(C : sig val cctxt: Client_context.prompter end) = struct
|
||||
where <public_key> is the public key in Base58."
|
||||
|
||||
let public_key = Unencrypted.public_key
|
||||
|
||||
let public_key_hash = Unencrypted.public_key_hash
|
||||
|
||||
let neuterize sk_uri =
|
||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||
return (Unencrypted.make_pk (Signature.Secret_key.to_public_key sk))
|
||||
|
||||
let sign ?watermark sk_uri buf =
|
||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||
return (Signature.sign ?watermark sk buf)
|
||||
|
||||
let deterministic_nonce sk_uri buf =
|
||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||
return (Signature.deterministic_nonce sk buf)
|
||||
|
||||
let deterministic_nonce_hash sk_uri buf =
|
||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||
return (Signature.deterministic_nonce_hash sk buf)
|
||||
|
||||
end
|
||||
|
@ -100,6 +100,20 @@ module Make(N : sig val scheme : string end) = struct
|
||||
public_key ?interactive uri >>=? fun pk ->
|
||||
return (Signature.Public_key.hash pk, Some pk)
|
||||
|
||||
let get_signature base pkh msg =
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
?headers
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.authorized_keys () () ()
|
||||
>>=? function
|
||||
| Some authorized_keys ->
|
||||
P.authenticate
|
||||
authorized_keys
|
||||
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||
return_some signature
|
||||
| None -> return_none
|
||||
|
||||
let sign ?watermark uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
let msg =
|
||||
@ -107,19 +121,7 @@ module Make(N : sig val scheme : string end) = struct
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
?headers
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.authorized_keys () () () >>=? fun authorized_keys ->
|
||||
begin match authorized_keys with
|
||||
| Some authorized_keys ->
|
||||
P.authenticate
|
||||
authorized_keys
|
||||
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||
return_some signature
|
||||
| None -> return_none
|
||||
end >>=? fun signature ->
|
||||
get_signature base pkh msg >>=? fun signature ->
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
?headers
|
||||
@ -128,6 +130,28 @@ module Make(N : sig val scheme : string end) = struct
|
||||
signature
|
||||
msg
|
||||
|
||||
let deterministic_nonce uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
get_signature base pkh msg >>=? fun signature ->
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
?headers
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.deterministic_nonce ((), pkh)
|
||||
signature
|
||||
msg
|
||||
|
||||
let deterministic_nonce_hash uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
get_signature base pkh msg >>=? fun signature ->
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
?headers
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.deterministic_nonce_hash ((), pkh)
|
||||
signature
|
||||
msg
|
||||
|
||||
end
|
||||
|
||||
let make_base host port =
|
||||
|
@ -105,6 +105,7 @@ let secp256k1_ctx =
|
||||
|
||||
type error +=
|
||||
| LedgerError of Ledgerwallet.Transport.error
|
||||
| Ledger_deterministic_nonce_not_implemented
|
||||
|
||||
let error_encoding =
|
||||
let open Data_encoding in
|
||||
@ -125,6 +126,20 @@ let () =
|
||||
(function LedgerError e -> Some e | _ -> None)
|
||||
(fun e -> LedgerError e)
|
||||
|
||||
let () =
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id: "signer.ledger.deterministic_nonce_not_implemented"
|
||||
~title: "Ledger deterministic_nonce(_hash) not implemented"
|
||||
~description: "The deterministic_nonce(_hash) functionality \
|
||||
is not implemented by the ledger"
|
||||
~pp:(fun ppf () ->
|
||||
Format.fprintf ppf "Asked the ledger to generate a deterministic nonce (hash), \
|
||||
but this functionality is not yet implemented")
|
||||
Data_encoding.unit
|
||||
(function Ledger_deterministic_nonce_not_implemented -> Some () | _ -> None)
|
||||
(fun () -> Ledger_deterministic_nonce_not_implemented)
|
||||
|
||||
type id =
|
||||
| Animals of Ledger_names.t * Ledgerwallet_tezos.curve option
|
||||
| Pkh of Signature.Public_key_hash.t
|
||||
@ -481,6 +496,10 @@ let sign ?watermark sk_uri msg =
|
||||
return (Signature.of_p256 signature)
|
||||
end
|
||||
|
||||
let deterministic_nonce _ _ = fail Ledger_deterministic_nonce_not_implemented
|
||||
let deterministic_nonce_hash _ _ = fail Ledger_deterministic_nonce_not_implemented
|
||||
let supports_deterministic_nonces _ = return_false
|
||||
|
||||
let commands =
|
||||
let open Clic in
|
||||
let group =
|
||||
|
@ -97,6 +97,16 @@ module Make(S : sig
|
||||
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||
msg
|
||||
|
||||
let deterministic_nonce sk_uri msg =
|
||||
Remote.deterministic_nonce
|
||||
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||
msg
|
||||
|
||||
let deterministic_nonce_hash sk_uri msg =
|
||||
Remote.deterministic_nonce_hash
|
||||
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||
msg
|
||||
|
||||
end
|
||||
|
||||
let make_sk sk =
|
||||
@ -186,4 +196,3 @@ let parse_base_uri s =
|
||||
| Some scheme -> failwith "Unknown scheme: %s" scheme
|
||||
| None -> failwith "Unknown scheme: <empty>"
|
||||
with Invalid_argument msg -> failwith "Malformed URI: %s" msg
|
||||
|
||||
|
@ -33,12 +33,22 @@ module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) = struct
|
||||
|
||||
let sign ?watermark path pkh msg =
|
||||
let msg =
|
||||
match watermark with
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
type request_type =
|
||||
| Sign_request
|
||||
| Deterministic_nonce_request
|
||||
| Deterministic_nonce_hash_request
|
||||
|
||||
let build_request pkh data signature = function
|
||||
| Sign_request ->
|
||||
Request.Sign { Sign.Request.pkh ; data ; signature }
|
||||
| Deterministic_nonce_request ->
|
||||
Request.Deterministic_nonce
|
||||
{ Deterministic_nonce.Request.pkh ; data ; signature }
|
||||
| Deterministic_nonce_hash_request ->
|
||||
Request.Deterministic_nonce_hash
|
||||
{ Deterministic_nonce_hash.Request.pkh ; data ; signature }
|
||||
|
||||
let signer_operation path pkh msg request_type =
|
||||
begin
|
||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.send
|
||||
@ -55,15 +65,37 @@ module Make(P : sig
|
||||
return_some signature
|
||||
end
|
||||
end >>=? fun signature ->
|
||||
let req = { Sign.Request.pkh ; data = msg ; signature } in
|
||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.send
|
||||
conn Request.encoding (Request.Sign req) >>=? fun () ->
|
||||
let req = build_request pkh msg signature request_type in
|
||||
Lwt_utils_unix.Socket.send conn Request.encoding req >>=? fun () ->
|
||||
return conn
|
||||
|
||||
let sign ?watermark path pkh msg =
|
||||
let msg =
|
||||
match watermark with
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
signer_operation path pkh msg Sign_request >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.recv conn
|
||||
(result_encoding Sign.Response.encoding) >>=? fun res ->
|
||||
Lwt_unix.close conn >>= fun () ->
|
||||
Lwt.return res
|
||||
|
||||
let deterministic_nonce path pkh msg =
|
||||
signer_operation path pkh msg Deterministic_nonce_request >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.recv conn
|
||||
(result_encoding Deterministic_nonce.Response.encoding) >>=? fun res ->
|
||||
Lwt_unix.close conn >>= fun () ->
|
||||
Lwt.return res
|
||||
|
||||
let deterministic_nonce_hash path pkh msg =
|
||||
signer_operation path pkh msg Deterministic_nonce_hash_request >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.recv conn
|
||||
(result_encoding Deterministic_nonce_hash.Response.encoding) >>=? fun res ->
|
||||
Lwt_unix.close conn >>= fun () ->
|
||||
Lwt.return res
|
||||
|
||||
let public_key path pkh =
|
||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.send
|
||||
@ -108,6 +140,14 @@ module Make(P : sig
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
sign ?watermark path pkh msg
|
||||
|
||||
let deterministic_nonce uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
deterministic_nonce path pkh msg
|
||||
|
||||
let deterministic_nonce_hash uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
deterministic_nonce_hash path pkh msg
|
||||
|
||||
end
|
||||
|
||||
module Tcp = struct
|
||||
@ -154,6 +194,14 @@ module Make(P : sig
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
sign ?watermark path pkh msg
|
||||
|
||||
let deterministic_nonce uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
deterministic_nonce path pkh msg
|
||||
|
||||
let deterministic_nonce_hash uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||
deterministic_nonce_hash path pkh msg
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -66,3 +66,11 @@ let public_key_hash ?interactive pk_uri =
|
||||
let sign ?watermark sk_uri buf =
|
||||
secret_key sk_uri >>=? fun sk ->
|
||||
return (Signature.sign ?watermark sk buf)
|
||||
|
||||
let deterministic_nonce sk_uri buf =
|
||||
secret_key sk_uri >>=? fun sk ->
|
||||
return (Signature.deterministic_nonce sk buf)
|
||||
|
||||
let deterministic_nonce_hash sk_uri buf =
|
||||
secret_key sk_uri >>=? fun sk ->
|
||||
return (Signature.deterministic_nonce_hash sk buf)
|
||||
|
@ -23,35 +23,57 @@
|
||||
(* *)
|
||||
(*****************************************************************************)
|
||||
|
||||
module type Authenticated_request = sig
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
val to_sign:
|
||||
pkh: Signature.Public_key_hash.t ->
|
||||
data: MBytes.t ->
|
||||
MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
module type Tag = sig
|
||||
val tag: int
|
||||
end
|
||||
|
||||
module Make_authenticated_request(T: Tag) : Authenticated_request = struct
|
||||
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
|
||||
let to_sign ~pkh ~data =
|
||||
let tag = MBytes.make 1 '0' in
|
||||
MBytes.set_int8 tag 0 T.tag;
|
||||
MBytes.concat ""
|
||||
[ MBytes.of_string "\x04" ;
|
||||
tag;
|
||||
Signature.Public_key_hash.to_bytes pkh ;
|
||||
data ]
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
conv
|
||||
(fun { pkh ; data ; signature } ->
|
||||
(pkh, data, signature))
|
||||
(fun (pkh, data, signature) ->
|
||||
{ pkh ; data ; signature })
|
||||
(obj3
|
||||
(req "pkh" Signature.Public_key_hash.encoding)
|
||||
(req "data" bytes)
|
||||
(opt "signature" Signature.encoding))
|
||||
|
||||
end
|
||||
|
||||
module Sign = struct
|
||||
|
||||
module Request = struct
|
||||
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
|
||||
let to_sign ~pkh ~data =
|
||||
MBytes.concat ""
|
||||
[ MBytes.of_string "\x04" ;
|
||||
Signature.Public_key_hash.to_bytes pkh ;
|
||||
data ]
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
conv
|
||||
(fun { pkh ; data ; signature } ->
|
||||
(pkh, data, signature))
|
||||
(fun (pkh, data, signature) ->
|
||||
{ pkh ; data ; signature })
|
||||
(obj3
|
||||
(req "pkh" Signature.Public_key_hash.encoding)
|
||||
(req "data" bytes)
|
||||
(opt "signature" Signature.encoding))
|
||||
|
||||
end
|
||||
module Request = Make_authenticated_request (struct let tag = 1 end)
|
||||
|
||||
module Response = struct
|
||||
|
||||
@ -64,6 +86,37 @@ module Sign = struct
|
||||
|
||||
end
|
||||
|
||||
module Deterministic_nonce = struct
|
||||
|
||||
module Request = Make_authenticated_request (struct let tag = 2 end)
|
||||
|
||||
module Response = struct
|
||||
|
||||
type t = MBytes.t
|
||||
|
||||
let encoding =
|
||||
Data_encoding.(obj1 (req "deterministic_nonce" bytes))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Deterministic_nonce_hash = struct
|
||||
|
||||
module Request = Make_authenticated_request (struct let tag = 3 end)
|
||||
|
||||
module Response = struct
|
||||
|
||||
type t = MBytes.t
|
||||
|
||||
let encoding =
|
||||
Data_encoding.(obj1 (req "deterministic_nonce_hash" bytes))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
module Public_key = struct
|
||||
|
||||
module Request = struct
|
||||
@ -118,6 +171,8 @@ module Request = struct
|
||||
| Sign of Sign.Request.t
|
||||
| Public_key of Public_key.Request.t
|
||||
| Authorized_keys
|
||||
| Deterministic_nonce of Deterministic_nonce.Request.t
|
||||
| Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
@ -141,6 +196,20 @@ module Request = struct
|
||||
(obj1 (req "kind" (constant "authorized_keys")))
|
||||
(function Authorized_keys -> Some () | _ -> None)
|
||||
(fun () -> Authorized_keys) ;
|
||||
case (Tag 3)
|
||||
~title:"Deterministic_nonce"
|
||||
(merge_objs
|
||||
(obj1 (req "kind" (constant "deterministic_nonce")))
|
||||
Deterministic_nonce.Request.encoding)
|
||||
(function Deterministic_nonce req -> Some ((), req) | _ -> None)
|
||||
(fun ((), req) -> Deterministic_nonce req) ;
|
||||
case (Tag 4)
|
||||
~title:"Deterministic_nonce_hash"
|
||||
(merge_objs
|
||||
(obj1 (req "kind" (constant "deterministic_nonce_hash")))
|
||||
Deterministic_nonce_hash.Request.encoding)
|
||||
(function Deterministic_nonce_hash req -> Some ((), req) | _ -> None)
|
||||
(fun ((), req) -> Deterministic_nonce_hash req) ;
|
||||
]
|
||||
|
||||
end
|
||||
|
@ -23,20 +23,22 @@
|
||||
(* *)
|
||||
(*****************************************************************************)
|
||||
|
||||
module type Authenticated_request = sig
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
val to_sign:
|
||||
pkh: Signature.Public_key_hash.t ->
|
||||
data: MBytes.t ->
|
||||
MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
module Sign : sig
|
||||
|
||||
module Request : sig
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
val to_sign:
|
||||
pkh: Signature.Public_key_hash.t ->
|
||||
data: MBytes.t ->
|
||||
MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
module Request : Authenticated_request
|
||||
|
||||
module Response : sig
|
||||
type t = Signature.t
|
||||
@ -45,6 +47,28 @@ module Sign : sig
|
||||
|
||||
end
|
||||
|
||||
module Deterministic_nonce : sig
|
||||
|
||||
module Request : Authenticated_request
|
||||
|
||||
module Response : sig
|
||||
type t = MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Deterministic_nonce_hash : sig
|
||||
|
||||
module Request : Authenticated_request
|
||||
|
||||
module Response : sig
|
||||
type t = MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Public_key : sig
|
||||
|
||||
module Request : sig
|
||||
@ -70,12 +94,15 @@ module Authorized_keys : sig
|
||||
|
||||
end
|
||||
|
||||
|
||||
module Request : sig
|
||||
|
||||
type t =
|
||||
| Sign of Sign.Request.t
|
||||
| Public_key of Public_key.Request.t
|
||||
| Authorized_keys
|
||||
| Deterministic_nonce of Deterministic_nonce.Request.t
|
||||
| Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t
|
||||
val encoding : t Data_encoding.t
|
||||
|
||||
end
|
||||
|
@ -23,17 +23,19 @@
|
||||
(* *)
|
||||
(*****************************************************************************)
|
||||
|
||||
|
||||
let query =
|
||||
let open RPC_query in
|
||||
query (fun signature -> signature)
|
||||
|+ opt_field
|
||||
~descr: "Must be provided if the signer requires \
|
||||
authentication. In this case, it must be the signature \
|
||||
of the public key hash and message concatenated, by one \
|
||||
of the keys authorized by the signer."
|
||||
"authentication" Signature.rpc_arg (fun signature -> signature)
|
||||
|> seal
|
||||
|
||||
let sign =
|
||||
let query =
|
||||
let open RPC_query in
|
||||
query (fun signature -> signature)
|
||||
|+ opt_field
|
||||
~descr: "Must be provided if the signer requires \
|
||||
authentication. In this case, it must be the signature \
|
||||
of the public key hash and message concatenated, by one \
|
||||
of the keys authorized by the signer."
|
||||
"authentication" Signature.rpc_arg (fun signature -> signature)
|
||||
|> seal in
|
||||
RPC_service.post_service
|
||||
~description: "Sign a piece of data with a given remote key"
|
||||
~query
|
||||
@ -41,6 +43,22 @@ let sign =
|
||||
~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
|
||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||
|
||||
let deterministic_nonce =
|
||||
RPC_service.post_service
|
||||
~description: "Obtain some random data generated deterministically from some piece of data with a given remote key"
|
||||
~query
|
||||
~input: Data_encoding.bytes
|
||||
~output: Data_encoding.(obj1 (req "deterministic_nonce" bytes))
|
||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||
|
||||
let deterministic_nonce_hash =
|
||||
RPC_service.post_service
|
||||
~description: "Obtain the hash of some random data generated deterministically from some piece of data with a given remote key"
|
||||
~query
|
||||
~input: Data_encoding.bytes
|
||||
~output: Data_encoding.(obj1 (req "deterministic_nonce_hash" bytes))
|
||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||
|
||||
let public_key =
|
||||
RPC_service.get_service
|
||||
~description: "Retrieve the public key of a given remote key"
|
||||
|
@ -27,6 +27,14 @@ val sign :
|
||||
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||
Signature.t option, MBytes.t, Signature.t) RPC_service.t
|
||||
|
||||
val deterministic_nonce :
|
||||
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||
Signature.t option, MBytes.t, MBytes.t) RPC_service.t
|
||||
|
||||
val deterministic_nonce_hash :
|
||||
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||
Signature.t option, MBytes.t, MBytes.t) RPC_service.t
|
||||
|
||||
val public_key :
|
||||
([ `GET ], unit, unit * Signature.Public_key_hash.t,
|
||||
unit, unit, Signature.Public_key.t) RPC_service.t
|
||||
|
Loading…
Reference in New Issue
Block a user