From 87d00641134ca7ed6a37d70847a057b27ac5c730 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Wed, 20 Nov 2019 18:17:35 +0100 Subject: [PATCH] Multisig made robust to replay attack --- src/main/run/of_michelson.ml | 10 ++++------ src/test/contracts/multisig.ligo | 7 +++++-- src/test/multisig_tests.ml | 26 +++++++++++++++++++------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/main/run/of_michelson.ml b/src/main/run/of_michelson.ml index ad7bb28f5..012e928ea 100644 --- a/src/main/run/of_michelson.ml +++ b/src/main/run/of_michelson.ml @@ -83,13 +83,11 @@ let evaluate_michelson ?options program = let%bind etv = evaluate ?options program in ex_value_ty_to_michelson etv -let pack_message_lambda (lambda:Michelson.t) = - let open Memory_proto_alpha.Protocol.Script_typed_ir in - let input_ty = Lambda_t (Unit_t None , List_t ((Operation_t None),None,false) , None) in - let%bind lambda = +let pack_payload (payload:Michelson.t) ty = + let%bind payload = Trace.trace_tzresult_lwt (simple_error "error parsing message") @@ - Memory_proto_alpha.parse_michelson_data lambda input_ty in + Memory_proto_alpha.parse_michelson_data payload ty in let%bind data = Trace.trace_tzresult_lwt (simple_error "error packing message") @@ - Memory_proto_alpha.pack input_ty lambda in + Memory_proto_alpha.pack ty payload in ok @@ data diff --git a/src/test/contracts/multisig.ligo b/src/test/contracts/multisig.ligo index 31f42836f..e252ba335 100644 --- a/src/test/contracts/multisig.ligo +++ b/src/test/contracts/multisig.ligo @@ -2,8 +2,10 @@ type counter_t is nat type threshold_t is nat type authorized_keys_t is list(key) +type id_t is string type storage_t is record + id : id_t ; counter : counter_t ; threshold : threshold_t ; auth : authorized_keys_t ; @@ -28,14 +30,15 @@ function check_message (const param : check_message_pt; if param.counter =/= s.counter then failwith ("Counters does not match") else block { - var packed_msg : bytes := bytes_pack(message) ; + const packed_payload : bytes = + bytes_pack((message , param.counter , s.id , get_chain_id)); var valid : nat := 0n ; for sig in list param.signatures block { var is_valid : bool := False ; for pk in list s.auth block { - if crypto_check(pk,sig,packed_msg) then is_valid := True + if crypto_check(pk,sig,packed_payload) then is_valid := True else skip; }; diff --git a/src/test/multisig_tests.ml b/src/test/multisig_tests.ml index 7c38899a5..ef3ba594e 100644 --- a/src/test/multisig_tests.ml +++ b/src/test/multisig_tests.ml @@ -33,22 +33,26 @@ let str_keys (raw_pk, raw_sk) = let (sk_str:string) = Base58.simple_encode (Ed25519.Secret_key.b58check_encoding) raw_sk in (pk_str,sk_str) -let sign_message (msg : expression) raw_sk : string result = +let sign_message (payload : expression) raw_sk : string result = let open Tezos_crypto in let (sk : Signature.secret_key) = Signature.Ed25519 raw_sk in let%bind program,_ = get_program () in - let%bind (msg : Tezos_utils.Michelson.michelson) = + let%bind code = let env = Ast_typed.program_environment program in - Ligo.Run.Of_simplified.compile_expression ~env ~state:(Typer.Solver.initial_state) msg - in - let%bind msg' = Ligo.Run.Of_michelson.pack_message_lambda msg in - let (signed_data:Signature.t) = Signature.sign sk msg' in + Compile.Of_simplified.compile_expression_as_function + ~env ~state:(Typer.Solver.initial_state) payload in + let Compiler.Program.{input=_;output=(Ex_ty payload_ty);body=_} = code in + let%bind (payload: Tezos_utils.Michelson.michelson) = + Ligo.Run.Of_michelson.evaluate_michelson code in + let%bind packed_payload = Ligo.Run.Of_michelson.pack_payload payload payload_ty in + let (signed_data:Signature.t) = Signature.sign sk packed_payload in let signature_str = Signature.to_b58check signed_data in ok signature_str let init_storage threshold counter pkeys = let keys = List.map (fun el -> e_key @@ fst @@ str_keys el) pkeys in ez_e_record [ + ("id" , e_string "MULTISIG" ) ; ("counter" , e_nat counter ) ; ("threshold" , e_nat threshold) ; ("auth" , e_typed_list keys t_key ) ; @@ -59,11 +63,19 @@ let empty_op_list = let empty_message = e_lambda "arguments" (Some t_unit) (Some (t_list t_operation)) empty_op_list +let chain_id_zero = e_chain_id @@ Tezos_crypto.Base58.simple_encode + Tezos_base__TzPervasives.Chain_id.b58check_encoding + Tezos_base__TzPervasives.Chain_id.zero (* sign the same message 'msg' with the secret keys of 'keys' *) let params counter msg keys = let aux = fun acc sk -> - let%bind signature = sign_message msg (snd sk) in + let payload = e_tuple + [ msg ; + e_nat counter ; + e_string "MULTISIG" ; + chain_id_zero ] in + let%bind signature = sign_message payload (snd sk) in ok @@ (e_signature signature)::acc in let%bind signed_msgs = Trace.bind_fold_list aux [] keys in ok @@ e_constructor