Shell: allow to prefix signed data by a watermark

This commit is contained in:
Grégoire Henry 2018-05-25 15:50:31 +02:00
parent 2a85c34c67
commit 5e17430815
17 changed files with 105 additions and 38 deletions

View File

@ -127,7 +127,9 @@ module type SIGNER = sig
val neuterize : secret_key -> public_key Lwt.t val neuterize : secret_key -> public_key Lwt.t
val public_key : public_key -> Signature.Public_key.t 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_hash : public_key -> Signature.Public_key_hash.t Lwt.t
val sign : secret_key -> MBytes.t -> Signature.t tzresult Lwt.t val sign :
?watermark: Signature.watermark ->
secret_key -> MBytes.t -> Signature.t tzresult Lwt.t
end end
let signers_table : (string, (module SIGNER) * bool) Hashtbl.t = Hashtbl.create 13 let signers_table : (string, (module SIGNER) * bool) Hashtbl.t = Hashtbl.create 13
@ -149,14 +151,14 @@ let find_signer_for_key cctxt ~scheme =
let registered_signers () : (string * (module SIGNER)) list = let registered_signers () : (string * (module SIGNER)) list =
Hashtbl.fold (fun k (v, _) acc -> (k, v) :: acc) signers_table [] Hashtbl.fold (fun k (v, _) acc -> (k, v) :: acc) signers_table []
let sign cctxt ((Sk_locator { scheme }) as skloc) buf = let sign ?watermark cctxt ((Sk_locator { scheme }) as skloc) buf =
find_signer_for_key cctxt ~scheme >>=? fun signer -> find_signer_for_key cctxt ~scheme >>=? fun signer ->
let module Signer = (val signer : SIGNER) in let module Signer = (val signer : SIGNER) in
Signer.sk_of_locator skloc >>=? fun t -> Signer.sk_of_locator skloc >>=? fun t ->
Signer.sign t buf Signer.sign ?watermark t buf
let append cctxt loc buf = let append ?watermark cctxt loc buf =
sign cctxt loc buf >>|? fun signature -> sign ?watermark cctxt loc buf >>|? fun signature ->
Signature.concat buf signature Signature.concat buf signature
let register_key cctxt ?(force=false) let register_key cctxt ?(force=false)

View File

@ -90,9 +90,11 @@ module type SIGNER = sig
val public_key_hash : public_key -> Signature.Public_key_hash.t Lwt.t val public_key_hash : public_key -> Signature.Public_key_hash.t Lwt.t
(** [public_key_hash pk] is the hash of [pk]. *) (** [public_key_hash pk] is the hash of [pk]. *)
val sign : secret_key -> MBytes.t -> Signature.t tzresult Lwt.t val sign :
(** [sign sk data] is signature obtained by signing [data] with ?watermark: Signature.watermark ->
[sk]. *) secret_key -> MBytes.t -> Signature.t tzresult Lwt.t
(** [sign ?watermark sk data] is signature obtained by signing [data] with
[sk]. *)
end end
val register_signer : (module SIGNER) -> unit val register_signer : (module SIGNER) -> unit
@ -103,10 +105,14 @@ val registered_signers : unit -> (string * (module SIGNER)) list
val find_signer_for_key : val find_signer_for_key :
#Client_context.io_wallet -> scheme:string -> (module SIGNER) tzresult Lwt.t #Client_context.io_wallet -> scheme:string -> (module SIGNER) tzresult Lwt.t
val sign : val sign :
?watermark:Signature.watermark ->
#Client_context.io_wallet -> #Client_context.io_wallet ->
sk_locator -> MBytes.t -> Signature.t tzresult Lwt.t sk_locator -> MBytes.t -> Signature.t tzresult Lwt.t
val append : val append :
?watermark:Signature.watermark ->
#Client_context.io_wallet -> #Client_context.io_wallet ->
sk_locator -> MBytes.t -> MBytes.t tzresult Lwt.t sk_locator -> MBytes.t -> MBytes.t tzresult Lwt.t

View File

@ -202,7 +202,7 @@ module Encrypted_signer : SIGNER = struct
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 = Lwt.return x let public_key x = Lwt.return x
let public_key_hash x = Lwt.return (Signature.Public_key.hash x) let public_key_hash x = Lwt.return (Signature.Public_key.hash x)
let sign t buf = return (Signature.sign t buf) let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
end end
let () = let () =

View File

@ -59,7 +59,7 @@ module Unencrypted_signer : SIGNER = struct
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 = Lwt.return x let public_key x = Lwt.return x
let public_key_hash x = Lwt.return (Signature.Public_key.hash x) let public_key_hash x = Lwt.return (Signature.Public_key.hash x)
let sign t buf = return (Signature.sign t buf) let sign ?watermark t buf = return (Signature.sign ?watermark t buf)
end end
let () = let () =

View File

@ -225,6 +225,8 @@ end
type t = MBytes.t type t = MBytes.t
type watermark = MBytes.t
let name = "Ed25519" let name = "Ed25519"
let title = "An Ed25519 signature" let title = "An Ed25519 signature"
@ -284,12 +286,24 @@ let pp ppf t = Format.fprintf ppf "%s" (to_b58check t)
let zero = MBytes.make size '\000' let zero = MBytes.make size '\000'
let sign sk msg = let sign ?watermark sk msg =
let msg =
Blake2B.to_bytes @@
Blake2B.hash_bytes @@
match watermark with
| None -> [msg]
| Some prefix -> [ prefix ; msg ] in
let signature = MBytes.create Sign.bytes in let signature = MBytes.create Sign.bytes in
Sign.sign ~sk ~msg ~signature ; Sign.sign ~sk ~msg ~signature ;
signature signature
let check pk signature msg = let check ?watermark pk signature msg =
let msg =
Blake2B.to_bytes @@
Blake2B.hash_bytes @@
match watermark with
| None -> [msg]
| Some prefix -> [ prefix ; msg ] in
Sign.verify ~pk ~signature ~msg Sign.verify ~pk ~signature ~msg
let generate_key ?seed () = let generate_key ?seed () =

View File

@ -9,5 +9,5 @@
(** Tezos - Ed25519 cryptography *) (** Tezos - Ed25519 cryptography *)
include S.SIGNATURE include S.SIGNATURE with type watermark = MBytes.t
include S.RAW_DATA with type t := t include S.RAW_DATA with type t := t

View File

@ -205,8 +205,9 @@ module type SIGNATURE = sig
val zero: t val zero: t
val sign: Secret_key.t -> MBytes.t -> t type watermark
val check: Public_key.t -> t -> MBytes.t -> bool val sign: ?watermark:watermark -> Secret_key.t -> MBytes.t -> t
val check: ?watermark:watermark -> Public_key.t -> t -> MBytes.t -> bool
val generate_key: ?seed:MBytes.t -> unit -> (Public_key_hash.t * Public_key.t * Secret_key.t) val generate_key: ?seed:MBytes.t -> unit -> (Public_key_hash.t * Public_key.t * Secret_key.t)

View File

@ -173,6 +173,8 @@ end
type t = Sign.plain Sign.t type t = Sign.plain Sign.t
type watermark = MBytes.t
let name = "Secp256k1" let name = "Secp256k1"
let title = "A Secp256k1 signature" let title = "A Secp256k1 signature"
@ -239,10 +241,22 @@ let pp ppf t = Format.fprintf ppf "%s" (to_b58check t)
let zero = of_bytes_exn (MBytes.make size '\000') let zero = of_bytes_exn (MBytes.make size '\000')
let sign sk msg = let sign ?watermark sk msg =
let msg =
Blake2B.to_bytes @@
Blake2B.hash_bytes @@
match watermark with
| None -> [msg]
| Some prefix -> [ prefix ; msg ] in
Sign.sign_exn context ~sk msg Sign.sign_exn context ~sk msg
let check public_key signature msg = let check ?watermark public_key signature msg =
let msg =
Blake2B.to_bytes @@
Blake2B.hash_bytes @@
match watermark with
| None -> [msg]
| Some prefix -> [ prefix ; msg ] in
Sign.verify_exn context ~pk:public_key ~msg ~signature Sign.verify_exn context ~pk:public_key ~msg ~signature
let generate_key ?(seed=Rand.generate 32) () = let generate_key ?(seed=Rand.generate 32) () =

View File

@ -9,6 +9,5 @@
(** Tezos - Secp256k1 cryptography *) (** Tezos - Secp256k1 cryptography *)
include S.SIGNATURE include S.SIGNATURE with type watermark = MBytes.t
include S.RAW_DATA with type t := t include S.RAW_DATA with type t := t

View File

@ -21,6 +21,12 @@ type secret_key =
| Ed25519 of Ed25519.Secret_key.t | Ed25519 of Ed25519.Secret_key.t
| Secp256k1 of Secp256k1.Secret_key.t | Secp256k1 of Secp256k1.Secret_key.t
type watermark =
| Block_header
| Endorsement
| Generic_operation
| Custom of MBytes.t
module Public_key_hash = struct module Public_key_hash = struct
type t = public_key_hash = type t = public_key_hash =
@ -432,37 +438,40 @@ let of_ed25519 s = Ed25519 s
let zero = of_ed25519 Ed25519.zero let zero = of_ed25519 Ed25519.zero
let hash msg = let bytes_of_watermark = function
Blake2B.(to_bytes (hash_bytes [msg])) | Block_header -> MBytes.of_string "\x01"
| Endorsement -> MBytes.of_string "\x02"
| Generic_operation -> MBytes.of_string "\x03"
| Custom bytes -> bytes
let sign secret_key message = let sign ?watermark secret_key message =
let message = hash message in let watermark = Option.map ~f:bytes_of_watermark watermark in
match secret_key with match secret_key with
| Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign sk message) | Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign ?watermark sk message)
| Secret_key.Secp256k1 sk -> of_secp256k1 (Secp256k1.sign sk message) | Secret_key.Secp256k1 sk -> of_secp256k1 (Secp256k1.sign ?watermark sk message)
let check public_key signature message = let check ?watermark public_key signature message =
let message = hash message in let watermark = Option.map ~f:bytes_of_watermark watermark in
match public_key, signature with match public_key, signature with
| Public_key.Ed25519 pk, Unknown signature -> begin | Public_key.Ed25519 pk, Unknown signature -> begin
match Ed25519.of_bytes_opt signature with match Ed25519.of_bytes_opt signature with
| Some s -> Ed25519.check pk s message | Some s -> Ed25519.check ?watermark pk s message
| None -> false | None -> false
end end
| Public_key.Secp256k1 pk, Unknown signature -> begin | Public_key.Secp256k1 pk, Unknown signature -> begin
match Secp256k1.of_bytes_opt signature with match Secp256k1.of_bytes_opt signature with
| Some s -> Secp256k1.check pk s message | Some s -> Secp256k1.check ?watermark pk s message
| None -> false | None -> false
end end
| Public_key.Ed25519 pk, Ed25519 signature -> | Public_key.Ed25519 pk, Ed25519 signature ->
Ed25519.check pk signature message Ed25519.check ?watermark pk signature message
| Public_key.Secp256k1 pk, Secp256k1 signature -> | Public_key.Secp256k1 pk, Secp256k1 signature ->
Secp256k1.check pk signature message Secp256k1.check ?watermark pk signature message
| Public_key.Ed25519 _, Secp256k1 _ -> false | Public_key.Ed25519 _, Secp256k1 _ -> false
| Public_key.Secp256k1 _, Ed25519 _ -> false | Public_key.Secp256k1 _, Ed25519 _ -> false
let append sk msg = let append ?watermark sk msg =
MBytes.concat "" [msg; (to_bytes (sign sk msg))] MBytes.concat "" [msg; (to_bytes (sign ?watermark sk msg))]
let concat msg signature = let concat msg signature =
MBytes.concat "" [msg; (to_bytes signature)] MBytes.concat "" [msg; (to_bytes signature)]

View File

@ -19,11 +19,20 @@ type secret_key =
| Ed25519 of Ed25519.Secret_key.t | Ed25519 of Ed25519.Secret_key.t
| Secp256k1 of Secp256k1.Secret_key.t | Secp256k1 of Secp256k1.Secret_key.t
type watermark =
| Block_header
| Endorsement
| Generic_operation
| Custom of MBytes.t
val bytes_of_watermark: watermark -> MBytes.t
include S.SIGNATURE with type Public_key_hash.t = public_key_hash include S.SIGNATURE with type Public_key_hash.t = public_key_hash
and type Public_key.t = public_key and type Public_key.t = public_key
and type Secret_key.t = secret_key and type Secret_key.t = secret_key
and type watermark := watermark
val append : secret_key -> MBytes.t -> MBytes.t val append : ?watermark:watermark -> secret_key -> MBytes.t -> MBytes.t
(** [append sk buf] is the concatenation of [buf] and the (** [append sk buf] is the concatenation of [buf] and the
serialization of the signature of [buf] signed by [sk]. *) serialization of the signature of [buf] signed by [sk]. *)

View File

@ -9,4 +9,4 @@
(** Tezos - Ed25519 cryptography *) (** Tezos - Ed25519 cryptography *)
include S.SIGNATURE include S.SIGNATURE with type watermark := MBytes.t

View File

@ -244,8 +244,10 @@ module type SIGNATURE = sig
val zero: t val zero: t
type watermark
(** Check a signature *) (** Check a signature *)
val check: Public_key.t -> t -> MBytes.t -> bool val check: ?watermark:watermark -> Public_key.t -> t -> MBytes.t -> bool
end end

View File

@ -9,4 +9,4 @@
(** Tezos - Secp256k1 cryptography *) (** Tezos - Secp256k1 cryptography *)
include S.SIGNATURE include S.SIGNATURE with type watermark := MBytes.t

View File

@ -15,5 +15,12 @@ type public_key =
| Ed25519 of Ed25519.Public_key.t | Ed25519 of Ed25519.Public_key.t
| Secp256k1 of Secp256k1.Public_key.t | Secp256k1 of Secp256k1.Public_key.t
type watermark =
| Block_header
| Endorsement
| Generic_operation
| Custom of MBytes.t
include S.SIGNATURE with type Public_key_hash.t = public_key_hash include S.SIGNATURE with type Public_key_hash.t = public_key_hash
and type Public_key.t = public_key and type Public_key.t = public_key
and type watermark := watermark

View File

@ -134,6 +134,7 @@ module Make (Context : CONTEXT) = struct
and type Signature.public_key_hash = Signature.public_key_hash and type Signature.public_key_hash = Signature.public_key_hash
and type Signature.public_key = Signature.public_key and type Signature.public_key = Signature.public_key
and type Signature.t = Signature.t and type Signature.t = Signature.t
and type Signature.watermark = Signature.watermark
and type 'a Micheline.canonical = 'a Micheline.canonical and type 'a Micheline.canonical = 'a Micheline.canonical
and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
@ -313,8 +314,10 @@ module Make (Context : CONTEXT) = struct
val zero: t val zero: t
type watermark
(** Check a signature *) (** Check a signature *)
val check: Public_key.t -> t -> MBytes.t -> bool val check: ?watermark:watermark -> Public_key.t -> t -> MBytes.t -> bool
end end

View File

@ -127,6 +127,7 @@ module Make (Context : CONTEXT) : sig
and type Signature.public_key_hash = Signature.public_key_hash and type Signature.public_key_hash = Signature.public_key_hash
and type Signature.public_key = Signature.public_key and type Signature.public_key = Signature.public_key
and type Signature.t = Signature.t and type Signature.t = Signature.t
and type Signature.watermark = Signature.watermark
and type 'a Micheline.canonical = 'a Micheline.canonical and type 'a Micheline.canonical = 'a Micheline.canonical
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
and type Data_encoding.json_schema = Data_encoding.json_schema and type Data_encoding.json_schema = Data_encoding.json_schema