From 8d1052f08f8bee1d3c3565d99576276b98dacffa Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Wed, 25 Jan 2023 23:46:21 -0500 Subject: [PATCH] Add DKG example --- Cargo.lock | 1 + crypto/dkg/Cargo.toml | 2 + crypto/dkg/src/bin/example.rs | 73 +++++++++++++++++++++++++++++++++++ crypto/dkg/src/frost.rs | 23 ++++++----- crypto/dkg/src/tests/frost.rs | 12 +++--- 5 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 crypto/dkg/src/bin/example.rs diff --git a/Cargo.lock b/Cargo.lock index 5b3d0ec6..23e8424e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1883,6 +1883,7 @@ dependencies = [ "schnorr-signatures", "subtle", "thiserror", + "tokio", "zeroize", ] diff --git a/crypto/dkg/Cargo.toml b/crypto/dkg/Cargo.toml index fbdcba75..a7e4ef40 100644 --- a/crypto/dkg/Cargo.toml +++ b/crypto/dkg/Cargo.toml @@ -32,6 +32,8 @@ ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std"] } schnorr = { package = "schnorr-signatures", path = "../schnorr", version = "0.2" } dleq = { path = "../dleq", version = "0.2", features = ["serialize"] } +tokio = { version = "1", features = ["full"] } + [dev-dependencies] ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std", "ristretto"] } diff --git a/crypto/dkg/src/bin/example.rs b/crypto/dkg/src/bin/example.rs new file mode 100644 index 00000000..a4f82d4a --- /dev/null +++ b/crypto/dkg/src/bin/example.rs @@ -0,0 +1,73 @@ +use std::collections::HashMap; + +use rand_core::OsRng; + +use ciphersuite::{Ciphersuite, Ristretto}; + +use tokio::sync::mpsc::{self, UnboundedSender, UnboundedReceiver}; + +use dkg::{ + ThresholdParams, + encryption::{EncryptionKeyMessage, EncryptedMessage}, + frost::{Commitments, SecretShare, KeyGenMachine}, +}; + +async fn dkg( + i: u16, + send: UnboundedSender>, + mut recv: UnboundedReceiver>, +) { + // Calculate the other participant's i + let other_i = i ^ 0b11; + + // A 2-of-2 multisig + let params = ThresholdParams::new(2, 2, i).unwrap(); + + // Create a key gen machine + let machine = KeyGenMachine::new(params, "DKG Example".to_string()); + // Generate coefficients + let (machine, commitments) = machine.generate_coefficients(&mut OsRng); + // Send everyone our commitments + send.send(commitments.serialize()).unwrap(); + + // Receive everyone else's commitments + let other_commitments = EncryptionKeyMessage::>::read::<&[u8]>( + &mut recv.recv().await.unwrap().as_ref(), + params, + ) + .unwrap(); + let mut all_commitments = HashMap::new(); + all_commitments.insert(other_i, other_commitments); + + // Generate secret shares + let (machine, shares) = machine.generate_secret_shares(&mut OsRng, all_commitments).unwrap(); + // Send everyone else their secret shares + send.send(shares[&other_i].serialize()).unwrap(); + + // Receive our shares from everyone else + let share = EncryptedMessage::>::read::<&[u8]>( + &mut recv.recv().await.unwrap().as_ref(), + params, + ) + .unwrap(); + let mut all_shares = HashMap::new(); + all_shares.insert(other_i, share); + + // Calculate our share + let (machine, _key) = machine.calculate_share(&mut OsRng, all_shares).unwrap(); + // Assume the process succeeded, though this should only be done ater everyone votes on the key + let _keys = machine.complete(); +} + +#[tokio::main] +async fn main() { + // Create a pair of channels + let (alice_send, alice_recv) = mpsc::unbounded_channel(); + let (bob_send, bob_recv) = mpsc::unbounded_channel(); + + // Spawn Alice + let alice = dkg::(1, alice_send, bob_recv); + // Spawn Bob + let bob = dkg::(2, bob_send, alice_recv); + tokio::join!(alice, bob); +} diff --git a/crypto/dkg/src/frost.rs b/crypto/dkg/src/frost.rs index 0bc7ac7a..26e52a75 100644 --- a/crypto/dkg/src/frost.rs +++ b/crypto/dkg/src/frost.rs @@ -370,7 +370,7 @@ impl KeyMachine { mut self, rng: &mut R, mut shares: HashMap>>, - ) -> Result, FrostError> { + ) -> Result<(BlameMachine, C::G), FrostError> { validate_map(&shares, &(1 ..= self.params.n()).collect::>(), self.params.i())?; let mut batch = BatchVerifier::new(shares.len()); @@ -423,16 +423,19 @@ impl KeyMachine { } let KeyMachine { commitments, encryption, params, secret } = self; - Ok(BlameMachine { - commitments, - encryption, - result: ThresholdCore { - params, - secret_share: secret, - group_key: stripes[0], - verification_shares, + Ok(( + BlameMachine { + commitments, + encryption, + result: ThresholdCore { + params, + secret_share: secret, + group_key: stripes[0], + verification_shares, + }, }, - }) + stripes[0], + )) } } diff --git a/crypto/dkg/src/tests/frost.rs b/crypto/dkg/src/tests/frost.rs index 34579758..68e0b673 100644 --- a/crypto/dkg/src/tests/frost.rs +++ b/crypto/dkg/src/tests/frost.rs @@ -93,7 +93,7 @@ pub fn frost_gen( .drain() .map(|(i, machine)| { let our_secret_shares = generate_secret_shares(&secret_shares, i); - let these_keys = machine.calculate_share(rng, our_secret_shares).unwrap().complete(); + let these_keys = machine.calculate_share(rng, our_secret_shares).unwrap().0.complete(); // Verify the verification_shares are agreed upon if verification_shares.is_none() { @@ -157,7 +157,7 @@ mod literal { blame = Some(None); None } else { - Some(machine.unwrap()) + Some(machine.unwrap().0) } }) .collect::>(); @@ -191,7 +191,7 @@ mod literal { }); None } else { - Some(machine.unwrap()) + Some(machine.unwrap().0) } }) .collect::>(); @@ -221,7 +221,7 @@ mod literal { }); None } else { - Some(machine.unwrap()) + Some(machine.unwrap().0) } }) .collect::>(); @@ -255,7 +255,7 @@ mod literal { }); None } else { - Some(machine.unwrap()) + Some(machine.unwrap().0) } }) .collect::>(); @@ -288,7 +288,7 @@ mod literal { }); None } else { - Some(machine.unwrap()) + Some(machine.unwrap().0) } }) .collect::>();