Skip to content

Commit 34a5fd0

Browse files
authored
Merge pull request #137 from LFDT-Lockness/key-share-preimages
Trusted-dealer can generate random share preimages
2 parents 5e621ac + 6a9838c commit 34a5fd0

File tree

10 files changed

+186
-80
lines changed

10 files changed

+186
-80
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ udigest = { version = "0.2.1", default-features = false }
2525
digest = { version = "0.10", default-features = false }
2626
sha2 = { version = "0.10", default-features = false }
2727

28-
rand = "0.8"
28+
rand = { version = "0.8", default-features = false }
2929
rand_core = { version = "0.6", default-features = false }
3030
rand_hash = { version = "0.1" }
3131
rand_dev = "0.1"
@@ -35,7 +35,7 @@ futures-util = { version = "0.3", default-features = false }
3535

3636
anyhow = "1"
3737
thiserror = "1"
38-
displaydoc = { version = "0.2", default-features = false }
38+
displaydoc = { version = "0.2.5", default-features = false }
3939

4040
serde = { version = "1", default-features = false }
4141
serde_with = { version = "2", default-features = false }

cggmp21/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## v0.6.1
4+
* Trusted dealer can generate shares at random or non-standard preimages [#137]
5+
36
## v0.6.0
47
* Update `hd-wallet` dep to v0.6 [#120]
58

cggmp21/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cggmp21"
3-
version = "0.6.0"
3+
version = "0.6.1"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
description = "TSS ECDSA implementation based on CGGMP21 paper"

cggmp21/src/trusted_dealer.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ impl<E: Curve, L: SecurityLevel> TrustedDealerBuilder<E, L> {
147147

148148
/// Generates [`IncompleteKeyShare`]s
149149
///
150+
/// For Shamir secret sharing, it's shared at points `1` to `n`
151+
///
150152
/// Returns error if provided inputs are invalid, or if internal
151153
/// error has occurred.
152154
pub fn generate_core_shares(
@@ -161,18 +163,80 @@ impl<E: Curve, L: SecurityLevel> TrustedDealerBuilder<E, L> {
161163

162164
/// Generates [`KeyShare`]s
163165
///
166+
/// For Shamir secret sharing, it's shared at points `1` to `n`
167+
///
164168
/// Returns error if provided inputs are invalid, or if internal
165169
/// error has occurred.
166170
pub fn generate_shares(
167-
mut self,
171+
self,
172+
rng: &mut (impl RngCore + CryptoRng),
173+
) -> Result<Vec<KeyShare<E, L>>, TrustedDealerError> {
174+
self.generate_shares_at_internal(
175+
key_share::trusted_dealer::TrustedDealerBuilder::generate_shares,
176+
rng,
177+
)
178+
}
179+
180+
/// Generates [`KeyShare`]s shared at preimages provided. Each share is
181+
/// going to have the given `preimages` as its `I` component.
182+
///
183+
/// Preimages are ignored for additive key shares.
184+
///
185+
/// Returns error if provided inputs are invalid, or if internal
186+
/// error has occurred.
187+
pub fn generate_shares_at(
188+
self,
189+
preimages: Vec<NonZero<generic_ec::Scalar<E>>>,
168190
rng: &mut (impl RngCore + CryptoRng),
169191
) -> Result<Vec<KeyShare<E, L>>, TrustedDealerError> {
192+
self.generate_shares_at_internal(
193+
|builder, rng| builder.generate_shares_at(preimages, rng),
194+
rng,
195+
)
196+
}
197+
198+
/// Generates [`KeyShare`]s shared at random points
199+
///
200+
/// Returns error if provided inputs are invalid, or if internal
201+
/// error has occurred.
202+
///
203+
/// For Shamir secret sharing, the points at which the value is shared at
204+
/// are chosen at random between `1` and `u16::MAX`. For additive shares,
205+
/// this is the same as [`TrustedDealerBuilder::generate_shares`]
206+
///
207+
/// Returns error if provided inputs are invalid, or if internal
208+
/// error has occurred.
209+
pub fn generate_shares_at_random(
210+
self,
211+
rng: &mut (impl rand_core::RngCore + rand_core::CryptoRng),
212+
) -> Result<Vec<KeyShare<E, L>>, TrustedDealerError> {
213+
self.generate_shares_at_internal(
214+
key_share::trusted_dealer::TrustedDealerBuilder::generate_shares_at_random,
215+
rng,
216+
)
217+
}
218+
219+
fn generate_shares_at_internal<R, F>(
220+
mut self,
221+
inner_generate: F,
222+
rng: &mut R,
223+
) -> Result<Vec<KeyShare<E, L>>, TrustedDealerError>
224+
where
225+
F: FnOnce(
226+
CoreBuilder<E>,
227+
&mut R,
228+
) -> Result<
229+
Vec<IncompleteKeyShare<E>>,
230+
key_share::trusted_dealer::TrustedDealerError,
231+
>,
232+
R: rand_core::RngCore + rand_core::CryptoRng,
233+
{
170234
let n = self.n;
171235
let enable_multiexp = self.enable_mulitexp;
172236
let enable_crt = self.enable_crt;
173237

174238
let primes = self.pregenerated_primes.take();
175-
let core_key_shares = self.inner.generate_shares(rng).map_err(Reason::CoreError)?;
239+
let core_key_shares = inner_generate(self.inner, rng).map_err(Reason::CoreError)?;
176240
let aux_data = if let Some(primes) = primes {
177241
generate_aux_data_with_primes(rng, primes, enable_multiexp, enable_crt)?
178242
} else {

key-share/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## v0.6.1
4+
* Trusted dealer can generate shares at random or non-standard preimages [#137]
5+
36
## v0.6.0
47
* Update `hd-wallet` dep to v0.6 [#120]
58

key-share/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "key-share"
3-
version = "0.6.0"
3+
version = "0.6.1"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
description = "Key share of any Threshold Signature Scheme (TSS)"

key-share/src/trusted_dealer.rs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,66 @@ impl<E: Curve> TrustedDealerBuilder<E> {
9797
///
9898
/// Returns error if provided inputs are invalid, or if internal
9999
/// error has occurred.
100+
///
101+
/// For Shamir secret sharing, it's shared at points `1` to `n`
102+
///
103+
/// Returns error if provided inputs are invalid, or if internal
104+
/// error has occurred.
100105
pub fn generate_shares(
101106
self,
102107
rng: &mut (impl rand_core::RngCore + rand_core::CryptoRng),
103108
) -> Result<Vec<CoreKeyShare<E>>, TrustedDealerError> {
104-
let shared_secret_key = self
105-
.shared_secret_key
106-
.unwrap_or_else(|| NonZero::<SecretScalar<_>>::random(rng));
107-
let shared_public_key = Point::generator() * &shared_secret_key;
108109
let key_shares_indexes = (1..=self.n)
109110
.map(|i| generic_ec::NonZero::from_scalar(Scalar::from(i)))
110111
.collect::<Option<Vec<_>>>()
111112
.ok_or(Reason::DeriveKeyShareIndex)?;
113+
self.generate_shares_at(key_shares_indexes, rng)
114+
}
115+
116+
/// Generates [`CoreKeyShare`]s shared at random points
117+
///
118+
/// Returns error if provided inputs are invalid, or if internal
119+
/// error has occurred.
120+
///
121+
/// For Shamir secret sharing, the points at which the value is shared at
122+
/// are chosen at random between `1` and `u16::MAX`. For additive shares,
123+
/// this is the same as [`TrustedDealerBuilder::generate_shares`]
124+
///
125+
/// Returns error if provided inputs are invalid, or if internal
126+
/// error has occurred.
127+
pub fn generate_shares_at_random(
128+
self,
129+
rng: &mut (impl rand_core::RngCore + rand_core::CryptoRng),
130+
) -> Result<Vec<CoreKeyShare<E>>, TrustedDealerError> {
131+
// The chance of scalars repeating is negligible for usual fields in EC.
132+
// But in any case the dupliactes are checked during the validation of
133+
// CoreKeyShare
134+
let points = (0..self.n)
135+
.map(|_| generic_ec::NonZero::<Scalar<E>>::random(rng))
136+
.collect();
137+
self.generate_shares_at(points, rng)
138+
}
139+
140+
/// Generates [`CoreKeyShare`]s shared at preimages provided. Each share is
141+
/// going to have the given `preimages` as its `I` component.
142+
///
143+
/// Preimages are ignored for additive key shares.
144+
///
145+
/// Returns error if provided inputs are invalid, or if internal
146+
/// error has occurred.
147+
pub fn generate_shares_at(
148+
self,
149+
preimages: Vec<NonZero<Scalar<E>>>,
150+
rng: &mut (impl rand_core::RngCore + rand_core::CryptoRng),
151+
) -> Result<Vec<CoreKeyShare<E>>, TrustedDealerError> {
152+
if preimages.len() != usize::from(self.n) {
153+
return Err(Reason::InvalidPreimages.into());
154+
}
155+
156+
let shared_secret_key = self
157+
.shared_secret_key
158+
.unwrap_or_else(|| NonZero::<SecretScalar<_>>::random(rng));
159+
let shared_public_key = Point::generator() * &shared_secret_key;
112160
let secret_shares = if let Some(t) = self.t {
113161
let f = generic_ec_zkp::polynomial::Polynomial::sample_with_const_term(
114162
rng,
@@ -120,7 +168,7 @@ impl<E: Curve> TrustedDealerBuilder<E> {
120168
Point::generator() * f.value::<_, Scalar<_>>(&Scalar::zero())
121169
);
122170

123-
key_shares_indexes
171+
preimages
124172
.iter()
125173
.map(|I_i| f.value(I_i))
126174
.map(|mut x_i| SecretScalar::new(&mut x_i))
@@ -150,7 +198,7 @@ impl<E: Curve> TrustedDealerBuilder<E> {
150198

151199
let vss_setup = self.t.map(|t| VssSetup {
152200
min_signers: t,
153-
I: key_shares_indexes,
201+
I: preimages,
154202
});
155203

156204
#[cfg(feature = "hd-wallet")]
@@ -198,6 +246,8 @@ enum Reason {
198246
DeriveKeyShareIndex,
199247
#[displaydoc("randomly generated share is zero - probability of that is negligible")]
200248
ZeroShare,
249+
#[displaydoc("invalid share preimages given")]
250+
InvalidPreimages,
201251
}
202252

203253
impl From<Reason> for TrustedDealerError {

tests/tests/it/trusted_dealer.rs

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,53 @@ fn trusted_dealer_generates_correct_shares<E: Curve>() {
2828
let mut rng = DevRng::new();
2929
let thresholds = [None, Some(2), Some(3), Some(5), Some(7), Some(10)];
3030

31+
let methods = [
32+
trusted_dealer::TrustedDealerBuilder::generate_shares,
33+
trusted_dealer::TrustedDealerBuilder::generate_shares_at_random,
34+
];
35+
3136
for n in [2, 3, 7, 10] {
3237
for &t in thresholds
3338
.iter()
3439
.filter(|t| t.map(|t| t <= n).unwrap_or(true))
3540
{
36-
println!("t={t:?} n={n}");
37-
let sk = NonZero::<SecretScalar<_>>::random(&mut rng);
38-
let shares = trusted_dealer::builder::<E, DummyLevel>(n)
39-
.set_threshold(t)
40-
.set_shared_secret_key(sk.clone())
41-
.generate_shares(&mut rng)
42-
.unwrap();
41+
for generate in methods {
42+
println!("t={t:?} n={n}");
43+
let sk = NonZero::<SecretScalar<_>>::random(&mut rng);
44+
let builder = trusted_dealer::builder::<E, DummyLevel>(n)
45+
.set_threshold(t)
46+
.set_shared_secret_key(sk.clone());
47+
let shares = generate(builder, &mut rng).unwrap();
4348

44-
// Choose `t` random key shares and reconstruct a secret key
45-
let t = t.unwrap_or(n);
46-
let t_shares = shares
47-
.choose_multiple(&mut rng, t.into())
48-
.cloned()
49-
.collect::<Vec<_>>();
49+
// Choose `t` random key shares and reconstruct a secret key
50+
let t = t.unwrap_or(n);
51+
let t_shares = shares
52+
.choose_multiple(&mut rng, t.into())
53+
.cloned()
54+
.collect::<Vec<_>>();
5055

51-
let sk_reconstructed = reconstruct_secret_key(&t_shares).unwrap();
52-
assert_eq!(
53-
{
54-
let sk: &Scalar<E> = sk.as_ref();
55-
sk
56-
},
57-
sk_reconstructed.as_ref()
58-
);
59-
assert_eq!(
60-
Point::generator() * &sk_reconstructed,
61-
shares[0].core.shared_public_key
62-
);
56+
let sk_reconstructed = reconstruct_secret_key(&t_shares).unwrap();
57+
assert_eq!(
58+
{
59+
let sk: &Scalar<E> = sk.as_ref();
60+
sk
61+
},
62+
sk_reconstructed.as_ref()
63+
);
64+
assert_eq!(
65+
Point::generator() * &sk_reconstructed,
66+
shares[0].core.shared_public_key
67+
);
6368

64-
// Check that `reconstruct_secret_key` works well with more than `t` shares
65-
let k = rng.gen_range((n.min(t + 1))..=n);
66-
let k_shares = shares
67-
.choose_multiple(&mut rng, k.into())
68-
.cloned()
69-
.collect::<Vec<_>>();
70-
let sk_reconstructed2 = reconstruct_secret_key(&k_shares).unwrap();
71-
assert_eq!(sk_reconstructed.as_ref(), sk_reconstructed2.as_ref());
69+
// Check that `reconstruct_secret_key` works well with more than `t` shares
70+
let k = rng.gen_range((n.min(t + 1))..=n);
71+
let k_shares = shares
72+
.choose_multiple(&mut rng, k.into())
73+
.cloned()
74+
.collect::<Vec<_>>();
75+
let sk_reconstructed2 = reconstruct_secret_key(&k_shares).unwrap();
76+
assert_eq!(sk_reconstructed.as_ref(), sk_reconstructed2.as_ref());
77+
}
7278
}
7379
}
7480
}

0 commit comments

Comments
 (0)