diff --git a/src/lib_client_base/client_keys.ml b/src/lib_client_base/client_keys.ml index 2f9c387e7..93954e3b0 100644 --- a/src/lib_client_base/client_keys.ml +++ b/src/lib_client_base/client_keys.ml @@ -127,7 +127,9 @@ module type SIGNER = sig 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 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 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 = 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 -> let module Signer = (val signer : SIGNER) in Signer.sk_of_locator skloc >>=? fun t -> - Signer.sign t buf + Signer.sign ?watermark t buf -let append cctxt loc buf = - sign cctxt loc buf >>|? fun signature -> +let append ?watermark cctxt loc buf = + sign ?watermark cctxt loc buf >>|? fun signature -> Signature.concat buf signature let register_key cctxt ?(force=false) diff --git a/src/lib_client_base/client_keys.mli b/src/lib_client_base/client_keys.mli index d40e4247f..9647ba638 100644 --- a/src/lib_client_base/client_keys.mli +++ b/src/lib_client_base/client_keys.mli @@ -90,9 +90,11 @@ module type SIGNER = sig val public_key_hash : public_key -> Signature.Public_key_hash.t Lwt.t (** [public_key_hash pk] is the hash of [pk]. *) - val sign : secret_key -> MBytes.t -> Signature.t tzresult Lwt.t - (** [sign sk data] is signature obtained by signing [data] with - [sk]. *) + val sign : + ?watermark: Signature.watermark -> + secret_key -> MBytes.t -> Signature.t tzresult Lwt.t + (** [sign ?watermark sk data] is signature obtained by signing [data] with + [sk]. *) end val register_signer : (module SIGNER) -> unit @@ -103,10 +105,14 @@ val registered_signers : unit -> (string * (module SIGNER)) list val find_signer_for_key : #Client_context.io_wallet -> scheme:string -> (module SIGNER) tzresult Lwt.t + val sign : + ?watermark:Signature.watermark -> #Client_context.io_wallet -> sk_locator -> MBytes.t -> Signature.t tzresult Lwt.t + val append : + ?watermark:Signature.watermark -> #Client_context.io_wallet -> sk_locator -> MBytes.t -> MBytes.t tzresult Lwt.t diff --git a/src/lib_client_base_unix/client_signer_encrypted.ml b/src/lib_client_base_unix/client_signer_encrypted.ml index 219b1d170..35d7a19aa 100644 --- a/src/lib_client_base_unix/client_signer_encrypted.ml +++ b/src/lib_client_base_unix/client_signer_encrypted.ml @@ -202,7 +202,7 @@ module Encrypted_signer : SIGNER = struct 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 sign t buf = return (Signature.sign t buf) + let sign ?watermark t buf = return (Signature.sign ?watermark t buf) end let () = diff --git a/src/lib_client_base_unix/client_signer_unencrypted.ml b/src/lib_client_base_unix/client_signer_unencrypted.ml index e83eff0fe..aa46246a4 100644 --- a/src/lib_client_base_unix/client_signer_unencrypted.ml +++ b/src/lib_client_base_unix/client_signer_unencrypted.ml @@ -59,7 +59,7 @@ module Unencrypted_signer : SIGNER = struct 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 sign t buf = return (Signature.sign t buf) + let sign ?watermark t buf = return (Signature.sign ?watermark t buf) end let () = diff --git a/src/lib_crypto/ed25519.ml b/src/lib_crypto/ed25519.ml index 618b42524..649e926ab 100644 --- a/src/lib_crypto/ed25519.ml +++ b/src/lib_crypto/ed25519.ml @@ -225,6 +225,8 @@ end type t = MBytes.t +type watermark = MBytes.t + let name = "Ed25519" 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 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 Sign.sign ~sk ~msg ~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 let generate_key ?seed () = diff --git a/src/lib_crypto/ed25519.mli b/src/lib_crypto/ed25519.mli index 6a866db93..4a4aa99ad 100644 --- a/src/lib_crypto/ed25519.mli +++ b/src/lib_crypto/ed25519.mli @@ -9,5 +9,5 @@ (** Tezos - Ed25519 cryptography *) -include S.SIGNATURE +include S.SIGNATURE with type watermark = MBytes.t include S.RAW_DATA with type t := t diff --git a/src/lib_crypto/s.ml b/src/lib_crypto/s.ml index e379c2feb..9f9865cc2 100644 --- a/src/lib_crypto/s.ml +++ b/src/lib_crypto/s.ml @@ -205,8 +205,9 @@ module type SIGNATURE = sig val zero: t - val sign: Secret_key.t -> MBytes.t -> t - val check: Public_key.t -> t -> MBytes.t -> bool + type watermark + 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) diff --git a/src/lib_crypto/secp256k1.ml b/src/lib_crypto/secp256k1.ml index 217ab049a..a1a8ff7f7 100644 --- a/src/lib_crypto/secp256k1.ml +++ b/src/lib_crypto/secp256k1.ml @@ -173,6 +173,8 @@ end type t = Sign.plain Sign.t +type watermark = MBytes.t + let name = "Secp256k1" 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 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 -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 let generate_key ?(seed=Rand.generate 32) () = diff --git a/src/lib_crypto/secp256k1.mli b/src/lib_crypto/secp256k1.mli index 022a788c3..7c6fbdee2 100644 --- a/src/lib_crypto/secp256k1.mli +++ b/src/lib_crypto/secp256k1.mli @@ -9,6 +9,5 @@ (** Tezos - Secp256k1 cryptography *) -include S.SIGNATURE - +include S.SIGNATURE with type watermark = MBytes.t include S.RAW_DATA with type t := t diff --git a/src/lib_crypto/signature.ml b/src/lib_crypto/signature.ml index 31d488204..ce9467d4c 100644 --- a/src/lib_crypto/signature.ml +++ b/src/lib_crypto/signature.ml @@ -21,6 +21,12 @@ type secret_key = | Ed25519 of Ed25519.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 type t = public_key_hash = @@ -432,37 +438,40 @@ let of_ed25519 s = Ed25519 s let zero = of_ed25519 Ed25519.zero -let hash msg = - Blake2B.(to_bytes (hash_bytes [msg])) +let bytes_of_watermark = function + | 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 message = hash message in +let sign ?watermark secret_key message = + let watermark = Option.map ~f:bytes_of_watermark watermark in match secret_key with - | Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign sk message) - | Secret_key.Secp256k1 sk -> of_secp256k1 (Secp256k1.sign sk message) + | Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign ?watermark sk message) + | Secret_key.Secp256k1 sk -> of_secp256k1 (Secp256k1.sign ?watermark sk message) -let check public_key signature message = - let message = hash message in +let check ?watermark public_key signature message = + let watermark = Option.map ~f:bytes_of_watermark watermark in match public_key, signature with | Public_key.Ed25519 pk, Unknown signature -> begin match Ed25519.of_bytes_opt signature with - | Some s -> Ed25519.check pk s message + | Some s -> Ed25519.check ?watermark pk s message | None -> false end | Public_key.Secp256k1 pk, Unknown signature -> begin match Secp256k1.of_bytes_opt signature with - | Some s -> Secp256k1.check pk s message + | Some s -> Secp256k1.check ?watermark pk s message | None -> false end | Public_key.Ed25519 pk, Ed25519 signature -> - Ed25519.check pk signature message + Ed25519.check ?watermark pk signature message | Public_key.Secp256k1 pk, Secp256k1 signature -> - Secp256k1.check pk signature message + Secp256k1.check ?watermark pk signature message | Public_key.Ed25519 _, Secp256k1 _ -> false | Public_key.Secp256k1 _, Ed25519 _ -> false -let append sk msg = - MBytes.concat "" [msg; (to_bytes (sign sk msg))] +let append ?watermark sk msg = + MBytes.concat "" [msg; (to_bytes (sign ?watermark sk msg))] let concat msg signature = MBytes.concat "" [msg; (to_bytes signature)] diff --git a/src/lib_crypto/signature.mli b/src/lib_crypto/signature.mli index 370eae951..acd72e308 100644 --- a/src/lib_crypto/signature.mli +++ b/src/lib_crypto/signature.mli @@ -19,11 +19,20 @@ type secret_key = | Ed25519 of Ed25519.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 and type Public_key.t = public_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 serialization of the signature of [buf] signed by [sk]. *) diff --git a/src/lib_protocol_environment/sigs/v1/ed25519.mli b/src/lib_protocol_environment/sigs/v1/ed25519.mli index 8735f56b1..76f34bcd7 100644 --- a/src/lib_protocol_environment/sigs/v1/ed25519.mli +++ b/src/lib_protocol_environment/sigs/v1/ed25519.mli @@ -9,4 +9,4 @@ (** Tezos - Ed25519 cryptography *) -include S.SIGNATURE +include S.SIGNATURE with type watermark := MBytes.t diff --git a/src/lib_protocol_environment/sigs/v1/s.mli b/src/lib_protocol_environment/sigs/v1/s.mli index 6c2b633e5..622c6ce9c 100644 --- a/src/lib_protocol_environment/sigs/v1/s.mli +++ b/src/lib_protocol_environment/sigs/v1/s.mli @@ -244,8 +244,10 @@ module type SIGNATURE = sig val zero: t + type watermark + (** Check a signature *) - val check: Public_key.t -> t -> MBytes.t -> bool + val check: ?watermark:watermark -> Public_key.t -> t -> MBytes.t -> bool end diff --git a/src/lib_protocol_environment/sigs/v1/secp256k1.mli b/src/lib_protocol_environment/sigs/v1/secp256k1.mli index a5de9c295..82977cae7 100644 --- a/src/lib_protocol_environment/sigs/v1/secp256k1.mli +++ b/src/lib_protocol_environment/sigs/v1/secp256k1.mli @@ -9,4 +9,4 @@ (** Tezos - Secp256k1 cryptography *) -include S.SIGNATURE +include S.SIGNATURE with type watermark := MBytes.t diff --git a/src/lib_protocol_environment/sigs/v1/signature.mli b/src/lib_protocol_environment/sigs/v1/signature.mli index 2fe66e8eb..4b259b9bd 100644 --- a/src/lib_protocol_environment/sigs/v1/signature.mli +++ b/src/lib_protocol_environment/sigs/v1/signature.mli @@ -15,5 +15,12 @@ type public_key = | Ed25519 of Ed25519.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 and type Public_key.t = public_key + and type watermark := watermark diff --git a/src/lib_protocol_environment/tezos_protocol_environment.ml b/src/lib_protocol_environment/tezos_protocol_environment.ml index 89107729b..c21f63806 100644 --- a/src/lib_protocol_environment/tezos_protocol_environment.ml +++ b/src/lib_protocol_environment/tezos_protocol_environment.ml @@ -134,6 +134,7 @@ module Make (Context : CONTEXT) = struct and type Signature.public_key_hash = Signature.public_key_hash and type Signature.public_key = Signature.public_key and type Signature.t = Signature.t + and type Signature.watermark = Signature.watermark and type 'a Micheline.canonical = 'a Micheline.canonical and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node @@ -313,8 +314,10 @@ module Make (Context : CONTEXT) = struct val zero: t + type watermark + (** Check a signature *) - val check: Public_key.t -> t -> MBytes.t -> bool + val check: ?watermark:watermark -> Public_key.t -> t -> MBytes.t -> bool end diff --git a/src/lib_protocol_environment/tezos_protocol_environment.mli b/src/lib_protocol_environment/tezos_protocol_environment.mli index 8c9fc6710..1fa917655 100644 --- a/src/lib_protocol_environment/tezos_protocol_environment.mli +++ b/src/lib_protocol_environment/tezos_protocol_environment.mli @@ -127,6 +127,7 @@ module Make (Context : CONTEXT) : sig and type Signature.public_key_hash = Signature.public_key_hash and type Signature.public_key = Signature.public_key and type Signature.t = Signature.t + and type Signature.watermark = Signature.watermark and type 'a Micheline.canonical = 'a Micheline.canonical and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node and type Data_encoding.json_schema = Data_encoding.json_schema