Skip to content

Commit aed1ea8

Browse files
feat(frost-core): add (de)serialization for VerifiableSecretSharingSharingSharingCommitment (#878)
* feat(frost-core): add (de)serialization for `VerifiableSecretSharingSharingSharingCommitment` * Update frost-core/src/keys.rs Co-authored-by: Conrado Gouvea <[email protected]> * Update frost-core/src/keys.rs Co-authored-by: Conrado Gouvea <[email protected]> * add tests * fix doc --------- Co-authored-by: Conrado Gouvea <[email protected]>
1 parent fc87f59 commit aed1ea8

File tree

8 files changed

+293
-1
lines changed

8 files changed

+293
-1
lines changed

frost-core/src/keys.rs

+24
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ where
327327
.collect::<Result<_, Error<C>>>()
328328
}
329329

330+
/// Serialize the whole commitment vector as a single byte vector.
331+
pub fn serialize_whole(&self) -> Result<Vec<u8>, Error<C>> {
332+
self.serialize().map(|v| v.concat())
333+
}
334+
330335
/// Returns VerifiableSecretSharingCommitment from an iterator of serialized
331336
/// CoefficientCommitments (e.g. a [`Vec<Vec<u8>>`]).
332337
pub fn deserialize<I, V>(serialized_coefficient_commitments: I) -> Result<Self, Error<C>>
@@ -342,6 +347,25 @@ where
342347
Ok(Self::new(coefficient_commitments))
343348
}
344349

350+
/// Deserialize a whole commitment vector from a single byte vector as returned by
351+
/// [`VerifiableSecretSharingCommitment::serialize_whole()`].
352+
pub fn deserialize_whole(bytes: &[u8]) -> Result<Self, Error<C>> {
353+
// Get size from the size of the generator
354+
let generator = <C::Group>::generator();
355+
let len = <C::Group>::serialize(&generator)
356+
.expect("serializing the generator always works")
357+
.as_ref()
358+
.len();
359+
360+
let serialized_coefficient_commitments = bytes.chunks_exact(len);
361+
362+
if !serialized_coefficient_commitments.remainder().is_empty() {
363+
return Err(Error::InvalidCoefficient);
364+
}
365+
366+
Self::deserialize(serialized_coefficient_commitments)
367+
}
368+
345369
/// Get the VerifyingKey matching this commitment vector (which is the first
346370
/// element in the vector), or an error if the vector is empty.
347371
pub(crate) fn verifying_key(&self) -> Result<VerifyingKey<C>, Error<C>> {

frost-core/src/tests/vss_commitment.rs

+123-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::{
44
keys::{CoefficientCommitment, VerifiableSecretSharingCommitment},
55
tests::helpers::generate_element,
6-
Group,
6+
Error, Group,
77
};
88
use debugless_unwrap::DebuglessUnwrap;
99
use rand_core::{CryptoRng, RngCore};
@@ -46,6 +46,40 @@ pub fn check_serialize_vss_commitment<C: Ciphersuite, R: RngCore + CryptoRng>(mu
4646
.all(|(e, c)| e.as_ref() == c));
4747
}
4848

49+
/// Test serialize_whole VerifiableSecretSharingCommitment
50+
pub fn check_serialize_whole_vss_commitment<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
51+
// Generate test CoefficientCommitments
52+
53+
// ---
54+
let input_1 = generate_element::<C, R>(&mut rng);
55+
let input_2 = generate_element::<C, R>(&mut rng);
56+
let input_3 = generate_element::<C, R>(&mut rng);
57+
58+
let coeff_comms = vec![
59+
CoefficientCommitment::<C>::new(input_1),
60+
CoefficientCommitment::new(input_2),
61+
CoefficientCommitment::new(input_3),
62+
];
63+
64+
// ---
65+
66+
let expected = [
67+
<C::Group>::serialize(&input_1).unwrap(),
68+
<C::Group>::serialize(&input_2).unwrap(),
69+
<C::Group>::serialize(&input_3).unwrap(),
70+
]
71+
.into_iter()
72+
.map(|element| element.as_ref().to_vec())
73+
.collect::<Vec<_>>()
74+
.concat();
75+
76+
let vss_commitment = VerifiableSecretSharingCommitment(coeff_comms)
77+
.serialize_whole()
78+
.unwrap();
79+
80+
assert!(expected == vss_commitment);
81+
}
82+
4983
/// Test deserialize VerifiableSecretSharingCommitment
5084
pub fn check_deserialize_vss_commitment<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
5185
// Generate test CoefficientCommitments
@@ -76,6 +110,40 @@ pub fn check_deserialize_vss_commitment<C: Ciphersuite, R: RngCore + CryptoRng>(
76110
assert!(expected == vss_value.unwrap());
77111
}
78112

113+
/// Test deserialize_whole VerifiableSecretSharingCommitment
114+
pub fn check_deserialize_whole_vss_commitment<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
115+
// Generate test CoefficientCommitments
116+
117+
// ---
118+
let input_1 = generate_element::<C, R>(&mut rng);
119+
let input_2 = generate_element::<C, R>(&mut rng);
120+
let input_3 = generate_element::<C, R>(&mut rng);
121+
122+
let coeff_comms = vec![
123+
CoefficientCommitment::<C>::new(input_1),
124+
CoefficientCommitment::new(input_2),
125+
CoefficientCommitment::new(input_3),
126+
];
127+
// ---
128+
129+
let expected = VerifiableSecretSharingCommitment(coeff_comms);
130+
131+
let data = vec![
132+
<C::Group>::serialize(&input_1).unwrap(),
133+
<C::Group>::serialize(&input_2).unwrap(),
134+
<C::Group>::serialize(&input_3).unwrap(),
135+
]
136+
.into_iter()
137+
.map(|element| element.as_ref().to_vec())
138+
.collect::<Vec<_>>()
139+
.concat();
140+
141+
let vss_value = VerifiableSecretSharingCommitment::deserialize_whole(&data);
142+
143+
assert!(vss_value.is_ok());
144+
assert!(expected == vss_value.unwrap());
145+
}
146+
79147
/// Test deserialize VerifiableSecretSharingCommitment error
80148
pub fn check_deserialize_vss_commitment_error<C: Ciphersuite, R: RngCore + CryptoRng>(
81149
mut rng: R,
@@ -109,6 +177,60 @@ pub fn check_deserialize_vss_commitment_error<C: Ciphersuite, R: RngCore + Crypt
109177
assert!(vss_value.is_err());
110178
}
111179

180+
/// Test deserialize_whole VerifiableSecretSharingCommitment error
181+
pub fn check_deserialize_whole_vss_commitment_error<C: Ciphersuite, R: RngCore + CryptoRng>(
182+
mut rng: R,
183+
commitment_helpers: &Value,
184+
) {
185+
// Generate test CoefficientCommitments
186+
187+
// ---
188+
let values = &commitment_helpers["elements"];
189+
190+
let input_1 = generate_element::<C, R>(&mut rng);
191+
let input_2 = generate_element::<C, R>(&mut rng);
192+
let input_3 = generate_element::<C, R>(&mut rng);
193+
194+
let serialized: <C::Group as Group>::Serialization =
195+
<C::Group as Group>::Serialization::try_from(
196+
hex::decode(values["invalid_element"].as_str().unwrap()).unwrap(),
197+
)
198+
.debugless_unwrap();
199+
// ---
200+
201+
let data = vec![
202+
<C::Group>::serialize(&input_1).unwrap(),
203+
<C::Group>::serialize(&input_2).unwrap(),
204+
<C::Group>::serialize(&input_3).unwrap(),
205+
serialized,
206+
]
207+
.into_iter()
208+
.map(|element| element.as_ref().to_vec())
209+
.collect::<Vec<_>>()
210+
.concat();
211+
212+
let vss_value = VerifiableSecretSharingCommitment::<C>::deserialize_whole(&data);
213+
214+
assert!(vss_value.is_err());
215+
216+
// Generate test CoefficientCommitments with invalid length
217+
218+
let mut data = vec![
219+
<C::Group>::serialize(&input_1).unwrap(),
220+
<C::Group>::serialize(&input_2).unwrap(),
221+
<C::Group>::serialize(&input_3).unwrap(),
222+
]
223+
.into_iter()
224+
.map(|element| element.as_ref().to_vec())
225+
.collect::<Vec<_>>()
226+
.concat();
227+
data.append(&mut vec![0x00]);
228+
229+
let vss_value = VerifiableSecretSharingCommitment::<C>::deserialize_whole(&data);
230+
231+
assert_eq!(vss_value, Err(Error::InvalidCoefficient));
232+
}
233+
112234
/// Test computing the public key package from a list of commitments.
113235
pub fn check_compute_public_key_package<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
114236
let max_signers = 3;

frost-ed25519/src/tests/vss_commitment.rs

+25
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,28 @@ fn check_serialize_vss_commitment() {
1616
frost_core::tests::vss_commitment::check_serialize_vss_commitment::<Ed25519Sha512, _>(rng);
1717
}
1818

19+
#[test]
20+
fn check_serialize_whole_vss_commitment() {
21+
let rng = rand::rngs::OsRng;
22+
frost_core::tests::vss_commitment::check_serialize_whole_vss_commitment::<Ed25519Sha512, _>(
23+
rng,
24+
);
25+
}
26+
1927
#[test]
2028
fn check_deserialize_vss_commitment() {
2129
let rng = rand::rngs::OsRng;
2230
frost_core::tests::vss_commitment::check_deserialize_vss_commitment::<Ed25519Sha512, _>(rng);
2331
}
2432

33+
#[test]
34+
fn check_deserialize_whole_vss_commitment() {
35+
let rng = rand::rngs::OsRng;
36+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment::<Ed25519Sha512, _>(
37+
rng,
38+
);
39+
}
40+
2541
#[test]
2642
fn check_deserialize_vss_commitment_error() {
2743
let rng = rand::rngs::OsRng;
@@ -30,6 +46,15 @@ fn check_deserialize_vss_commitment_error() {
3046
);
3147
}
3248

49+
#[test]
50+
fn check_deserialize_whole_vss_commitment_error() {
51+
let rng = rand::rngs::OsRng;
52+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment_error::<
53+
Ed25519Sha512,
54+
_,
55+
>(rng, &ELEMENTS);
56+
}
57+
3358
#[test]
3459
fn check_compute_public_key_package() {
3560
let rng = rand::rngs::OsRng;

frost-ed448/src/tests/vss_commitment.rs

+25
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,28 @@ fn check_serialize_vss_commitment() {
1616
frost_core::tests::vss_commitment::check_serialize_vss_commitment::<Ed448Shake256, _>(rng);
1717
}
1818

19+
#[test]
20+
fn check_serialize_whole_vss_commitment() {
21+
let rng = rand::rngs::OsRng;
22+
frost_core::tests::vss_commitment::check_serialize_whole_vss_commitment::<Ed448Shake256, _>(
23+
rng,
24+
);
25+
}
26+
1927
#[test]
2028
fn check_deserialize_vss_commitment() {
2129
let rng = rand::rngs::OsRng;
2230
frost_core::tests::vss_commitment::check_deserialize_vss_commitment::<Ed448Shake256, _>(rng);
2331
}
2432

33+
#[test]
34+
fn check_deserialize_whole_vss_commitment() {
35+
let rng = rand::rngs::OsRng;
36+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment::<Ed448Shake256, _>(
37+
rng,
38+
);
39+
}
40+
2541
#[test]
2642
fn check_deserialize_vss_commitment_error() {
2743
let rng = rand::rngs::OsRng;
@@ -30,6 +46,15 @@ fn check_deserialize_vss_commitment_error() {
3046
);
3147
}
3248

49+
#[test]
50+
fn check_deserialize_whole_vss_commitment_error() {
51+
let rng = rand::rngs::OsRng;
52+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment_error::<
53+
Ed448Shake256,
54+
_,
55+
>(rng, &ELEMENTS);
56+
}
57+
3358
#[test]
3459
fn check_compute_public_key_package() {
3560
let rng = rand::rngs::OsRng;

frost-p256/src/tests/vss_commitment.rs

+20
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,24 @@ fn check_serialize_vss_commitment() {
1616
frost_core::tests::vss_commitment::check_serialize_vss_commitment::<P256Sha256, _>(rng);
1717
}
1818

19+
#[test]
20+
fn check_serialize_whole_vss_commitment() {
21+
let rng = rand::rngs::OsRng;
22+
frost_core::tests::vss_commitment::check_serialize_whole_vss_commitment::<P256Sha256, _>(rng);
23+
}
24+
1925
#[test]
2026
fn check_deserialize_vss_commitment() {
2127
let rng = rand::rngs::OsRng;
2228
frost_core::tests::vss_commitment::check_deserialize_vss_commitment::<P256Sha256, _>(rng);
2329
}
2430

31+
#[test]
32+
fn check_deserialize_whole_vss_commitment() {
33+
let rng = rand::rngs::OsRng;
34+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment::<P256Sha256, _>(rng);
35+
}
36+
2537
#[test]
2638
fn check_deserialize_vss_commitment_error() {
2739
let rng = rand::rngs::OsRng;
@@ -30,6 +42,14 @@ fn check_deserialize_vss_commitment_error() {
3042
);
3143
}
3244

45+
#[test]
46+
fn check_deserialize_whole_vss_commitment_error() {
47+
let rng = rand::rngs::OsRng;
48+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment_error::<P256Sha256, _>(
49+
rng, &ELEMENTS,
50+
);
51+
}
52+
3353
#[test]
3454
fn check_compute_public_key_package() {
3555
let rng = rand::rngs::OsRng;

frost-ristretto255/src/tests/vss_commitment.rs

+26
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ fn check_serialize_vss_commitment() {
1616
frost_core::tests::vss_commitment::check_serialize_vss_commitment::<Ristretto255Sha512, _>(rng);
1717
}
1818

19+
#[test]
20+
fn check_serialize_whole_vss_commitment() {
21+
let rng = rand::rngs::OsRng;
22+
frost_core::tests::vss_commitment::check_serialize_whole_vss_commitment::<Ristretto255Sha512, _>(
23+
rng,
24+
);
25+
}
26+
1927
#[test]
2028
fn check_deserialize_vss_commitment() {
2129
let rng = rand::rngs::OsRng;
@@ -24,6 +32,15 @@ fn check_deserialize_vss_commitment() {
2432
);
2533
}
2634

35+
#[test]
36+
fn check_deserialize_whole_vss_commitment() {
37+
let rng = rand::rngs::OsRng;
38+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment::<
39+
Ristretto255Sha512,
40+
_,
41+
>(rng);
42+
}
43+
2744
#[test]
2845
fn check_deserialize_vss_commitment_error() {
2946
let rng = rand::rngs::OsRng;
@@ -33,6 +50,15 @@ fn check_deserialize_vss_commitment_error() {
3350
>(rng, &ELEMENTS);
3451
}
3552

53+
#[test]
54+
fn check_deserialize_whole_vss_commitment_error() {
55+
let rng = rand::rngs::OsRng;
56+
frost_core::tests::vss_commitment::check_deserialize_whole_vss_commitment_error::<
57+
Ristretto255Sha512,
58+
_,
59+
>(rng, &ELEMENTS);
60+
}
61+
3662
#[test]
3763
fn check_compute_public_key_package() {
3864
let rng = rand::rngs::OsRng;

0 commit comments

Comments
 (0)