multisig : non quadratic signature check

This commit is contained in:
Lesenechal Remi 2019-11-21 17:11:04 +01:00
parent 88a0f33fca
commit 17ecf12fa3
2 changed files with 57 additions and 45 deletions

View File

@ -12,10 +12,12 @@ type storage_t is record
end
// I/O types
type message_t is (unit -> list(operation))
type signatures_t is list(key_hash * signature)
type check_message_pt is record
counter : counter_t ;
message : (unit -> list(operation)) ;
signatures : list(signature) ;
message : message_t ;
signatures : signatures_t ;
end
type contract_return_t is (list(operation) * storage_t)
@ -25,7 +27,7 @@ type entry_point_t is
function check_message (const param : check_message_pt;
const s : storage_t) : contract_return_t is block {
var message : (unit -> list(operation)) := param.message ;
var message : message_t := param.message ;
if param.counter =/= s.counter then
failwith ("Counters does not match")
@ -34,17 +36,20 @@ function check_message (const param : check_message_pt;
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_payload) then is_valid := True
var keys : authorized_keys_t := s.auth ;
for pkh_sig in list param.signatures block {
case keys of
| nil -> skip
| key # tl -> block {
keys := tl ;
if pkh_sig.0 = crypto_hash_key(key) then
if crypto_check(key,pkh_sig.1,packed_payload) then valid := valid + 1n ;
else failwith ("Invalid signature")
else skip;
};
if is_valid then valid := valid + 1n
else failwith ("Invalid signature")
}
end
};
if valid < s.threshold then
failwith ("Not enough signatures passed the check")
else s.counter := s.counter + 1n ;

View File

@ -24,18 +24,18 @@ open Ast_simplified
let gen_keys = fun () ->
let open Tezos_crypto in
let (_,raw_pk,raw_sk) = Ed25519.generate_key () in
(raw_pk,raw_sk)
let (raw_pkh,raw_pk,raw_sk) = Signature.generate_key () in
(raw_pkh,raw_pk,raw_sk)
let str_keys (raw_pk, raw_sk) =
let str_keys (raw_pkh, raw_pk, raw_sk) =
let open Tezos_crypto in
let (pk_str:string) = Base58.simple_encode (Ed25519.Public_key.b58check_encoding) raw_pk in
let (sk_str:string) = Base58.simple_encode (Ed25519.Secret_key.b58check_encoding) raw_sk in
(pk_str,sk_str)
let sk_str = Signature.Secret_key.to_b58check raw_sk in
let pk_str = Signature.Public_key.to_b58check raw_pk in
let pkh_str = Signature.Public_key_hash.to_b58check raw_pkh in
(pkh_str,pk_str,sk_str)
let sign_message (payload : expression) raw_sk : string result =
let sign_message (payload : expression) 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 code =
let env = Ast_typed.program_environment program in
@ -50,7 +50,11 @@ let sign_message (payload : expression) raw_sk : string result =
ok signature_str
let init_storage threshold counter pkeys =
let keys = List.map (fun el -> e_key @@ fst @@ str_keys el) pkeys in
let keys = List.map
(fun el ->
let (_,pk_str,_) = str_keys el in
e_key @@ pk_str)
pkeys in
ez_e_record [
("id" , e_string "MULTISIG" ) ;
("counter" , e_nat counter ) ;
@ -67,23 +71,25 @@ 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 ->
(* sign the message 'msg' with 'keys', if 'is_valid'=false the providid signature will be incorrect *)
let params counter msg keys is_validl =
let aux = fun acc (key,is_valid) ->
let (_,_pk,sk) = key in
let (pkh,_,_) = str_keys key in
let payload = e_tuple
[ msg ;
e_nat counter ;
e_string "MULTISIG" ;
e_string (if is_valid then "MULTISIG" else "XX") ;
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
let%bind signature = sign_message payload sk in
ok @@ (e_pair (e_key_hash pkh) (e_signature signature))::acc in
let%bind signed_msgs = Trace.bind_fold_list aux [] (List.rev @@ List.combine keys is_validl) in
ok @@ e_constructor
"CheckMessage"
(ez_e_record [
("counter" , e_nat counter ) ;
("message" , msg) ;
("signatures" , e_typed_list signed_msgs t_signature ) ;
("signatures" , e_typed_list signed_msgs (t_pair (t_key_hash,t_signature)) ) ;
])
@ -92,7 +98,7 @@ let not_enough_1_of_2 () =
let%bind program,_ = get_program () in
let exp_failwith = "Not enough signatures passed the check" in
let keys = gen_keys () in
let%bind test_params = params 0 empty_message [keys] in
let%bind test_params = params 0 empty_message [keys] [true] in
let%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 2 0 [keys;gen_keys()])) exp_failwith in
ok ()
@ -101,20 +107,20 @@ let unmatching_counter () =
let%bind program,_ = get_program () in
let exp_failwith = "Counters does not match" in
let keys = gen_keys () in
let%bind test_params = params 1 empty_message [keys] in
let%bind test_params = params 1 empty_message [keys] [true] in
let%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 1 0 [keys])) exp_failwith in
ok ()
(* Provide one invalid signature when the threshold is one of one key *)
(* Provide one invalid signature (correct key but incorrect signature)
when the threshold is one of one key *)
let invalid_1_of_1 () =
let%bind program,_ = get_program () in
let exp_failwith = "Invalid signature" in
let keys = gen_keys () in
let invalid_keys = gen_keys () in
let%bind test_params = params 0 empty_message [keys] in
let keys = [gen_keys ()] in
let%bind test_params = params 0 empty_message keys [false] in
let%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 1 0 [invalid_keys])) exp_failwith in
program "main" (e_pair test_params (init_storage 1 0 keys)) exp_failwith in
ok ()
(* Provide one valid signature when the threshold is one of one key *)
@ -123,7 +129,7 @@ let valid_1_of_1 () =
let keys = gen_keys () in
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
(fun n ->
let%bind params = params n empty_message [keys] in
let%bind params = params n empty_message [keys] [true] in
ok @@ e_pair params (init_storage 1 n [keys])
)
(fun n ->
@ -134,11 +140,11 @@ let valid_1_of_1 () =
(* Provive two valid signatures when the threshold is two of three keys *)
let valid_2_of_3 () =
let%bind program,_ = get_program () in
let keys = [gen_keys (); gen_keys ()] in
let st_keys = gen_keys() :: keys in
let param_keys = [gen_keys (); gen_keys ()] in
let st_keys = param_keys @ [gen_keys ()] in
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
(fun n ->
let%bind params = params n empty_message keys in
let%bind params = params n empty_message param_keys [true;true] in
ok @@ e_pair params (init_storage 2 n st_keys)
)
(fun n ->
@ -147,12 +153,13 @@ let valid_2_of_3 () =
ok ()
(* Provide one invalid signature and two valid signatures when the threshold is two of three keys *)
let invalid_3_of_2 () =
let invalid_3_of_3 () =
let%bind program,_ = get_program () in
let valid_keys = [gen_keys() ; gen_keys()] in
let invalid_key = gen_keys () in
let st_keys = gen_keys () :: valid_keys in
let%bind test_params = params 0 empty_message (invalid_key::valid_keys) in
let param_keys = valid_keys @ [invalid_key] in
let st_keys = valid_keys @ [gen_keys ()] in
let%bind test_params = params 0 empty_message param_keys [false;true;true] in
let exp_failwith = "Invalid signature" in
let%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 2 0 st_keys)) exp_failwith in
@ -163,7 +170,7 @@ let not_enough_2_of_3 () =
let%bind program,_ = get_program () in
let valid_keys = [gen_keys() ; gen_keys()] in
let st_keys = gen_keys () :: valid_keys in
let%bind test_params = params 0 empty_message (valid_keys) in
let%bind test_params = params 0 empty_message (valid_keys) [true;true] in
let exp_failwith = "Not enough signatures passed the check" in
let%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 3 0 st_keys)) exp_failwith in
@ -176,6 +183,6 @@ let main = test_suite "Multisig" [
test "invalid_1_of_1" invalid_1_of_1 ;
test "not_enough_signature" not_enough_1_of_2 ;
test "valid_2_of_3" valid_2_of_3 ;
test "invalid_3_of_3" invalid_3_of_2 ;
test "invalid_3_of_3" invalid_3_of_3 ;
test "not_enough_2_of_3" not_enough_2_of_3 ;
]