Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assert that t <= n/2 and add examples to the readme #25

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,57 @@ Rushing adversary is a common assumption in Multiparty Computation (MPC). In FS-
in this write-up we show how by adjusting FS-DKG to key rotation for threshold ecdsa the above shortcomings are avoided.

## Our Model
We use standard proactive security assumptions. The protocol will be run by $n$ parties. We assume honest majority, that is, number of corruptions is $t<n/2$. The adversary is malicious, and rushing.
We use standard proactive security assumptions. The protocol will be run by $n$ parties. We assume honest majority, that is, number of corruptions is $t<=n/2$. The adversary is malicious, and rushing.
For communication, the parties have access to a broadcast channel (can be implemented via a bulletin board).
For threshold ECDSA, we focus on [GG20](https://eprint.iacr.org/2020/540.pdf) protocol, currently considered state of the art and most widely deployed threshold ecdsa scheme (e.g. [multi-party-ecdsa](https://github.com/ZenGo-X/multi-party-ecdsa), [tss-lib](https://github.com/binance-chain/tss-lib)).

## How To Use
### Refresh a Key
Each party calls `RefreshMessage::distribute(key)` on their `LocalKey` and broadcasts the `RefreshMessage` while saving their new `DecryptionKey`. <br>
After recieving all the refresh messages each party calls `RefreshMessage::collect(..)` with a vector of all the refresh messages, a mutable reference to their own key, and their new `DecryptionKey`, This will validate all the refresh messages, and if all the proofs are correct it will update the local key to contain the new decryption keys of all the parties.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:
recieving -> receiving


Example:
```rust
// All parties should run this
let mut party_i_key: LocalKey<_>;
let (party_i_refresh_message, party_i_new_decryption_key) = RefreshMessage::distribute(party_i_key);
broadcast(party_i_refresh_message);
let vec_refresh_messages = recv_from_broadcast();
RefreshMessage::collect(&vec_refresh_messages, &mut party_i_key, party_i_new_decryption_key, &[])?;
```

### Replacing a party
Each party that wants to join first generates a `JoinMessage` via `JoinMessage::distribute()` and broadcasts it to the current parties. <br>
The existing parties choose the index(who are they replacing) for the joining party.
Note that this part is delicate and needs to happen outside of the library because it requires some kind of mutual agreement, and you cannot trust the new party to communicate which party are they replacing. <br>
After agreeing on the index each party modifies the join message to contain the index `join_message.party_index = Some(index)`. <br>
Each existing party calls `RefreshMessage::replace(join_message, local_key)` with the join message and its own local key, this returns a refresh message and a new decryption key, just like in a Key Refresh, and they all broadcast the `RefreshMessage`. <br>
Each existing party recieves all the broadcasted refresh messages and calls `RefreshMessage::collect(..)` with a vector of all the refresh messages, a mutable reference to their own key, the new `DecryptionKey`, and a slice of all the join messages(`JoinMessage`) <br>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:
recieves -> receives

This will validate both the refresh messages and the join messages and if all the proofs are correct it will update the local key both as a refresh(new decryption keys) and replace the existing parties with the new ones. <br>
The new party calls `join_message.collect(..)` with the broadcasted `RefreshMessage` of the existing parties and all the join messages which returns a new `LocalKey` for the new party.

Example:
```rust
// PoV of the new party
let (join_message, new_party_decryption_key) = JoinMessage::distribute();
broadcast(join_message);
let new_party_index = recv_broadcast();
let vec_refresh_messages = recv_from_broadcast();
let new_party_local_key = join_message.collect(&vec_refresh_messages, new_party_decryption_key, &[])?;

// PoV of the other parties
let mut party_i_key: LocalKey<_>;
let mut join_message = recv_broadcast();
let new_index = decide_who_to_replace(&join_message);
broadcast(new_index);
assert!(recv_from_broadcast().iter().all(|index| index == new_index));
join_message.party_index = Some(new_index);
let (party_i_refresh_message, party_i_new_decryption_key) = RefreshMessage::replace(join_message, party_i_key)?;
broadcast(party_i_refresh_message);
let vec_refresh_messages = recv_from_broadcast();
RefreshMessage::collect(&vec_refresh_messages, &mut party_i_key, party_i_new_decryption_key, &[join_message])?;
```

## High-level Description of FS-DKG
Here we give a short description of the FS-DKG protocol.
FS-DKG works in one round. This round includes a single broadcast message from each party $P_j$. For Setup, we assume every party in the system has a public/private key pair for Paillier encryption scheme.
Expand Down Expand Up @@ -54,4 +101,3 @@ The third relevant work is Jens Groth' [Non interactive DKG and DKR](https://epr
## Acknowledgments
We thank Claudio Orlandi, Kobi Gurkan and Nikolaos Makriyannis for reviewing the note


2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! FS-DKR is a protocol for rotation of threshold ECDSA keys.
//!
//! We use standard proactive security assumptions. The protocol will be run
//! by $n$ parties. We assume honest majority, that is, number of corruptions is $t<n/2$.
//! by $n$ parties. We assume honest majority, that is, number of corruptions is $t<=n/2$.
//! The adversary is malicious, and rushing. For communication, the parties have access
//! to a broadcast channel (can be implemented via a bulletin board). For threshold ECDSA,
//! we focus on GG20 protocol, currently considered state of the art and most widely deployed
Expand Down
1 change: 1 addition & 0 deletions src/refresh_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl<P> RefreshMessage<P> {
P: ECPoint + Clone + Zeroize,
P::Scalar: PartialEq + Clone + Debug + Zeroize,
{
assert!(local_key.t <= local_key.n / 2);
let secret = local_key.keys_linear.x_i.clone();
// secret share old key
let (vss_scheme, secret_shares) =
Expand Down
2 changes: 1 addition & 1 deletion src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod tests {
fn test1() {
//simulate keygen
let t = 3;
let n = 5;
let n = 6;
let mut keys = simulate_keygen(t, n);

let old_keys = keys.clone();
Expand Down