Skip to content

Commit 9c9378f

Browse files
[bls12381/dkg] Check Commitments (Tolerate Equivocation Attack) (#1813)
1 parent 1cdfc32 commit 9c9378f

8 files changed

Lines changed: 240 additions & 125 deletions

File tree

cryptography/src/bls12381/benches/dkg_recovery.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use commonware_cryptography::{
88
use commonware_utils::quorum;
99
use criterion::{criterion_group, BatchSize, Criterion};
1010
use rand::{rngs::StdRng, SeedableRng};
11-
use std::{collections::HashMap, hint::black_box};
11+
use std::{collections::BTreeMap, hint::black_box};
1212

1313
/// Concurrency isn't used in DKG recovery, so we set it to 1.
1414
const CONCURRENCY: usize = 1;
@@ -43,7 +43,7 @@ fn benchmark_dkg_recovery(c: &mut Criterion) {
4343
);
4444

4545
// Create commitments and send shares to player
46-
let mut commitments = HashMap::new();
46+
let mut commitments = BTreeMap::new();
4747
for (idx, dealer) in contributors.iter().take(t as usize).enumerate() {
4848
let (_, commitment, shares) =
4949
Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
@@ -55,7 +55,7 @@ fn benchmark_dkg_recovery(c: &mut Criterion) {
5555
(player, commitments)
5656
},
5757
|(player, commitments)| {
58-
black_box(player.finalize(commitments, HashMap::new()).unwrap());
58+
black_box(player.finalize(commitments, BTreeMap::new()).unwrap());
5959
},
6060
BatchSize::SmallInput,
6161
);

cryptography/src/bls12381/benches/dkg_reshare_recovery.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use commonware_cryptography::{
88
use commonware_utils::quorum;
99
use criterion::{criterion_group, BatchSize, Criterion};
1010
use rand::{rngs::StdRng, SeedableRng};
11-
use std::{collections::HashMap, hint::black_box};
11+
use std::{collections::BTreeMap, hint::black_box};
1212

1313
// Configure contributors based on context
1414
#[cfg(not(full_bench))]
@@ -45,7 +45,7 @@ fn benchmark_dkg_reshare_recovery(c: &mut Criterion) {
4545

4646
// Create commitments and send shares to players
4747
let t = quorum(n as u32);
48-
let mut commitments = HashMap::new();
48+
let mut commitments = BTreeMap::new();
4949
for (dealer_idx, dealer) in contributors.iter().take(t as usize).enumerate() {
5050
let (_, commitment, shares) =
5151
Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
@@ -66,7 +66,7 @@ fn benchmark_dkg_reshare_recovery(c: &mut Criterion) {
6666
for player in players {
6767
outputs.push(
6868
player
69-
.finalize(commitments.clone(), HashMap::new())
69+
.finalize(commitments.clone(), BTreeMap::new())
7070
.unwrap(),
7171
);
7272
}
@@ -88,7 +88,7 @@ fn benchmark_dkg_reshare_recovery(c: &mut Criterion) {
8888
);
8989

9090
// Create commitments and send shares to player
91-
let mut commitments = HashMap::new();
91+
let mut commitments = BTreeMap::new();
9292
for (idx, dealer) in contributors.iter().take(t as usize).enumerate() {
9393
let (_, commitment, shares) = Dealer::<_, MinSig>::new(
9494
&mut rng,
@@ -103,7 +103,7 @@ fn benchmark_dkg_reshare_recovery(c: &mut Criterion) {
103103
(player, commitments)
104104
},
105105
|(player, commitments)| {
106-
black_box(player.finalize(commitments, HashMap::new()).unwrap());
106+
black_box(player.finalize(commitments, BTreeMap::new()).unwrap());
107107
},
108108
BatchSize::SmallInput,
109109
);

cryptography/src/bls12381/dkg/arbiter.rs

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ pub struct Output<V: Variant> {
5656
pub public: poly::Public<V>,
5757

5858
/// `2f + 1` commitments used to derive group polynomial.
59-
pub commitments: HashMap<u32, poly::Public<V>>,
59+
pub commitments: BTreeMap<u32, poly::Public<V>>,
6060

6161
/// Reveals published by dealers of selected commitments.
62-
pub reveals: HashMap<u32, Vec<Share>>,
62+
pub reveals: BTreeMap<u32, Vec<Share>>,
6363
}
6464

6565
/// Gather commitments, acknowledgements, and reveals from all dealers.
@@ -233,58 +233,47 @@ impl<P: PublicKey, V: Variant> Arbiter<P, V> {
233233

234234
// If there exist more than `2f + 1` commitments, take the first `2f + 1`
235235
// sorted by dealer index.
236-
let selected = self
237-
.commitments
238-
.into_iter()
239-
.take(dealer_threshold)
240-
.collect::<Vec<_>>();
236+
let mut commitments = BTreeMap::new();
237+
let mut reveals = BTreeMap::new();
238+
for (dealer_idx, (commitment, _, shares)) in
239+
self.commitments.into_iter().take(dealer_threshold)
240+
{
241+
commitments.insert(dealer_idx, commitment);
242+
243+
// If there are no reveals for dealer, skip
244+
if shares.is_empty() {
245+
continue;
246+
}
247+
reveals.insert(dealer_idx, shares);
248+
}
241249

242250
// Recover group
243251
let public = match self.previous {
244252
Some(previous) => {
245-
let mut commitments = BTreeMap::new();
246-
for (dealer_idx, (commitment, _, _)) in &selected {
247-
commitments.insert(*dealer_idx, commitment.clone());
248-
}
249253
match recover_public::<V>(
250254
&previous,
251-
commitments,
255+
&commitments,
252256
self.player_threshold,
253257
self.concurrency,
254258
) {
255259
Ok(public) => public,
256260
Err(e) => return (Err(e), self.disqualified),
257261
}
258262
}
259-
None => {
260-
let mut commitments = Vec::new();
261-
for (_, (commitment, _, _)) in &selected {
262-
commitments.push(commitment.clone());
263-
}
264-
match construct_public::<V>(commitments, self.player_threshold) {
265-
Ok(public) => public,
266-
Err(e) => return (Err(e), self.disqualified),
267-
}
268-
}
269-
};
270-
271-
// Generate output
272-
let mut commitments = HashMap::new();
273-
let mut reveals = HashMap::new();
274-
for (dealer_idx, (commitment, _, shares)) in selected {
275-
commitments.insert(dealer_idx, commitment);
276-
if shares.is_empty() {
277-
continue;
278-
}
279-
reveals.insert(dealer_idx, shares);
280-
}
281-
let output = Output {
282-
public,
283-
commitments,
284-
reveals,
263+
None => match construct_public::<V>(commitments.values(), self.player_threshold) {
264+
Ok(public) => public,
265+
Err(e) => return (Err(e), self.disqualified),
266+
},
285267
};
286268

287269
// Return output
288-
(Ok(output), self.disqualified)
270+
(
271+
Ok(Output {
272+
public,
273+
commitments,
274+
reveals,
275+
}),
276+
self.disqualified,
277+
)
289278
}
290279
}

0 commit comments

Comments
 (0)