ZenGo-X / multi-party-ecdsa

Rust implementation of {t,n}-threshold ECDSA (elliptic curve digital signature algorithm).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is there any instructions or examples for verifying the signature (for gg20)?

hcheng826 opened this issue · comments

commented

Thanks for the great repository! I have walked through the example for GG20 keygen and signing. I can successfully generate the signature but I don't actually know how to extract the public key and actually verify the generated signature.

Is there any instructions or examples that I can refer to? Thanks!

See #177 and in particular the comments after #177 (comment)

commented

thanks for the reply! will check that out!

commented

Unfortunately I didn't really get my question solved in that discussion 😢

But I tried another thing -

  1. Use the same shares to create 2 signatures from 2 different messages
  2. Recover the public keys from the message hashes and signatures
  3. And found that the recovered public keys are different

Is it a valid test? Or actually I am signing with different public key each time?

Here's my implementation in Javascript for reference: https://gist.github.com/hcheng826/2c3a4b98490a81052d8a4a1f8d4aad7f

output

recovered public key from signature 1: 
042583d64550be7b1121983675ff4c4bec6e539b63f80a6f10228f350edebcbe94db85af7728587fbe7fc8b956d2a22724f3ba4389faf40dd2e23e8adb80d72bd0
recovered public key from signature 2: 
049422bf5d394b8a5588caa4920c8c05d7a27a863e3ede8f87e8e65e97a4ef7cbec2f23ee87c0d7cad8e2ec1c6130145a9d9dc20a310e9e6709b4e4515a03e9e70

Is it a valid test?

Yes.

Or actually I am signing with different public key each time?

No. As long as you use the same private keys, you sign with the same public key.

And found that the recovered public keys are different

How are you recovering the public keys? Check the recovery id, that's a common source of issues.

commented

@ataki Thanks for the reply!

The recovery id I used is the id from the output of the signature. Is that the correct value to use?
Screenshot 2022-12-08 at 10 27 34 AM

To my knowledge the recid could be either 0 or 1, I tried with both values but still got different public keys 🤔
You mentioned that you had the same issue earlier, is there any code snippet that you can share? Appreciate it!

Try to print the signature as a hex string

let r = BigInt::from_bytes(sig.r.to_bytes().as_ref()).to_str_radix(16);
let s = BigInt::from_bytes(sig.s.to_bytes().as_ref()).to_str_radix(16);
let v = sig.recid;
let signature = format!("{:0>width$}{:0>width$}{:02x}", r, s, v, width = 64);

For Js could use the elliptic or ethers.js to verify it. Hopt it could help you
For Rust could use the check_sig

commented

Thanks for your reply! But I still cannot work it out 😥

I had another try, though. When I am tracing the code I found this: https://github.com/ZenGo-X/multi-party-ecdsa/blob/master/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen/rounds.rs#L324-L329

I guess that points out that y_sum_s in the local_share.json file is the joint public_key for this signature. Unfortunately when I tried to verify the signature with this public key, it still fails 😥

This is how I process y_sum_s and the signature coming from the ./gg20_signing command
https://gist.github.com/hcheng826/c494f639a7646f1758e0b6fab8c6d3d3

image

@hcheng826

replace

const msg = "hello";
const result = pk.verify(Buffer.from(sha3.keccak256(msg), "hex"), sig);

to

const msg = "68656c6c6f";
const result = pk.verify(Buffer.from(msg, "hex"), sig);

you need to get the actual message to be signed. data_to_sign changed

 let data_to_sign = "hello";
 let message = BigInt::from_bytes(data_to_sign.as_bytes());
 println!("message: {}", message.to_hex());
 
 => 68656c6c6f
commented

@peng-huang-ch Thank you so much! It works!!!!

Append the conversion in js for others' reference

const msg = "hello";
const msgHex = Buffer.from(msg).toString("hex");
const result = pk.verify(Buffer.from(msgHex, "hex"), sig);