1#[cfg(feature = "serde")]
2use alloc::string::String;
3
4use alloc::boxed::Box;
5use alloc::vec::Vec;
6use core::fmt;
7
8use generic_array::{typenum::U32, GenericArray};
9use rand_core::{CryptoRng, RngCore};
10
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13
14use crate::curve::{CurvePoint, CurveScalar, NonZeroCurveScalar};
15use crate::hashing_ds::{hash_to_polynomial_arg, hash_to_shared_secret, kfrag_signature_message};
16use crate::keys::{PublicKey, SecretKey, Signature, Signer};
17use crate::params::Parameters;
18use crate::secret_box::SecretBox;
19use crate::traits::fmt_public;
20
21#[cfg(feature = "default-serialization")]
22use crate::{DefaultDeserialize, DefaultSerialize};
23
24#[cfg(feature = "serde")]
25use crate::serde_bytes::{
26 deserialize_with_encoding, serialize_with_encoding, Encoding, TryFromBytes,
27};
28
29#[allow(clippy::upper_case_acronyms)]
30type KeyFragIDSize = U32;
31
32#[allow(clippy::upper_case_acronyms)]
33#[derive(Clone, Copy, Debug, PartialEq)]
34pub(crate) struct KeyFragID(GenericArray<u8, KeyFragIDSize>);
35
36impl KeyFragID {
37 fn random(rng: &mut impl RngCore) -> Self {
38 let mut bytes = GenericArray::<u8, KeyFragIDSize>::default();
39 rng.fill_bytes(&mut bytes);
40 Self(bytes)
41 }
42}
43
44impl AsRef<[u8]> for KeyFragID {
45 fn as_ref(&self) -> &[u8] {
46 self.0.as_ref()
47 }
48}
49
50#[cfg(feature = "serde")]
51impl Serialize for KeyFragID {
52 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
53 where
54 S: Serializer,
55 {
56 serialize_with_encoding(&self.0, serializer, Encoding::Hex)
57 }
58}
59
60#[cfg(feature = "serde")]
61impl<'de> Deserialize<'de> for KeyFragID {
62 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
63 where
64 D: Deserializer<'de>,
65 {
66 deserialize_with_encoding(deserializer, Encoding::Hex)
67 }
68}
69
70#[cfg(feature = "serde")]
71impl TryFromBytes for KeyFragID {
72 type Error = String;
73
74 fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
75 let arr = GenericArray::<u8, KeyFragIDSize>::from_exact_iter(bytes.iter().cloned())
76 .ok_or("Invalid length of a key frag ID")?;
77 Ok(Self(arr))
78 }
79}
80
81#[derive(Clone, Debug, PartialEq)]
82#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
83pub(crate) struct KeyFragProof {
84 pub(crate) commitment: CurvePoint,
85 signature_for_proxy: Signature,
86 pub(crate) signature_for_receiver: Signature,
87 delegating_key_signed: bool,
88 receiving_key_signed: bool,
89}
90
91fn none_unless<T>(x: Option<T>, predicate: bool) -> Option<T> {
92 if predicate {
93 x
94 } else {
95 None
96 }
97}
98
99impl KeyFragProof {
100 fn from_base(
101 rng: &mut (impl CryptoRng + RngCore),
102 base: &KeyFragBase<'_>,
103 kfrag_id: &KeyFragID,
104 kfrag_key: &CurveScalar,
105 sign_delegating_key: bool,
106 sign_receiving_key: bool,
107 ) -> Self {
108 let commitment = &base.params.u * kfrag_key;
109
110 let maybe_delegating_pk = Some(&base.delegating_pk);
111 let maybe_receiving_pk = Some(&base.receiving_pk);
112
113 let signature_for_receiver = base.signer.sign_with_rng(
114 rng,
115 kfrag_signature_message(
116 kfrag_id,
117 &commitment,
118 &base.precursor,
119 maybe_delegating_pk,
120 maybe_receiving_pk,
121 )
122 .as_ref(),
123 );
124
125 let signature_for_proxy = base.signer.sign_with_rng(
126 rng,
127 kfrag_signature_message(
128 kfrag_id,
129 &commitment,
130 &base.precursor,
131 none_unless(maybe_delegating_pk, sign_delegating_key),
132 none_unless(maybe_receiving_pk, sign_receiving_key),
133 )
134 .as_ref(),
135 );
136
137 Self {
138 commitment,
139 signature_for_proxy,
140 signature_for_receiver,
141 delegating_key_signed: sign_delegating_key,
142 receiving_key_signed: sign_receiving_key,
143 }
144 }
145}
146
147#[derive(Clone, Debug, PartialEq)]
149#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
150pub struct KeyFrag {
151 params: Parameters,
152 pub(crate) id: KeyFragID,
153 pub(crate) key: CurveScalar,
154 pub(crate) precursor: CurvePoint,
155 pub(crate) proof: KeyFragProof,
156}
157
158impl fmt::Display for KeyFrag {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 fmt_public("KeyFrag", &self.id, f)
161 }
162}
163
164#[derive(Debug, PartialEq, Eq)]
166pub enum KeyFragVerificationError {
167 IncorrectCommitment,
169 DelegatingKeyNotProvided,
172 ReceivingKeyNotProvided,
175 IncorrectSignature,
177}
178
179impl fmt::Display for KeyFragVerificationError {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 match self {
182 Self::IncorrectCommitment => write!(f, "Invalid kfrag commitment"),
183 Self::DelegatingKeyNotProvided => write!(f, "A signature of a delegating key was included in this kfrag but the key is not provided"),
184 Self::ReceivingKeyNotProvided => write!(f, "A signature of a receiving key was included in this kfrag, but the key is not provided"),
185 Self::IncorrectSignature => write!(f, "Failed to verify the kfrag signature"),
186 }
187 }
188}
189
190impl KeyFrag {
191 fn from_base(
192 rng: &mut (impl CryptoRng + RngCore),
193 base: &KeyFragBase<'_>,
194 sign_delegating_key: bool,
195 sign_receiving_key: bool,
196 ) -> Self {
197 let kfrag_id = KeyFragID::random(rng);
198
199 let share_index = hash_to_polynomial_arg(
204 &base.precursor,
205 &base.receiving_pk.to_point(),
206 &base.dh_point,
207 &kfrag_id,
208 );
209
210 let rk = poly_eval(&base.coefficients, &share_index);
213
214 let proof = KeyFragProof::from_base(
215 rng,
216 base,
217 &kfrag_id,
218 &rk,
219 sign_delegating_key,
220 sign_receiving_key,
221 );
222
223 Self {
224 params: base.params,
225 id: kfrag_id,
226 key: rk,
227 precursor: base.precursor,
228 proof,
229 }
230 }
231
232 #[allow(clippy::result_large_err)]
239 pub fn verify(
240 self,
241 verifying_pk: &PublicKey,
242 maybe_delegating_pk: Option<&PublicKey>,
243 maybe_receiving_pk: Option<&PublicKey>,
244 ) -> Result<VerifiedKeyFrag, (KeyFragVerificationError, Self)> {
245 let u = self.params.u;
246
247 let kfrag_id = self.id;
248 let key = self.key;
249 let commitment = self.proof.commitment;
250 let precursor = self.precursor;
251
252 if commitment != &u * &key {
254 return Err((KeyFragVerificationError::IncorrectCommitment, self));
255 }
256
257 if maybe_delegating_pk.is_none() && self.proof.delegating_key_signed {
260 return Err((KeyFragVerificationError::DelegatingKeyNotProvided, self));
261 }
262
263 if maybe_receiving_pk.is_none() && self.proof.receiving_key_signed {
264 return Err((KeyFragVerificationError::ReceivingKeyNotProvided, self));
265 }
266
267 if !self.proof.signature_for_proxy.verify(
270 verifying_pk,
271 kfrag_signature_message(
272 &kfrag_id,
273 &commitment,
274 &precursor,
275 none_unless(maybe_delegating_pk, self.proof.delegating_key_signed),
276 none_unless(maybe_receiving_pk, self.proof.receiving_key_signed),
277 )
278 .as_ref(),
279 ) {
280 return Err((KeyFragVerificationError::IncorrectSignature, self));
281 }
282
283 Ok(VerifiedKeyFrag { kfrag: self })
284 }
285
286 pub fn skip_verification(self) -> VerifiedKeyFrag {
292 VerifiedKeyFrag { kfrag: self }
293 }
294}
295
296#[cfg(feature = "default-serialization")]
297impl DefaultSerialize for KeyFrag {}
298
299#[cfg(feature = "default-serialization")]
300impl<'de> DefaultDeserialize<'de> for KeyFrag {}
301
302#[derive(Debug, Clone, PartialEq)]
306#[cfg_attr(feature = "serde", derive(Serialize))]
307#[cfg_attr(feature = "serde", serde(transparent))]
308pub struct VerifiedKeyFrag {
309 kfrag: KeyFrag,
310}
311
312impl fmt::Display for VerifiedKeyFrag {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 fmt_public("VerifiedKeyFrag", &self.kfrag.id, f)
315 }
316}
317
318impl VerifiedKeyFrag {
319 pub(crate) fn from_base(
320 rng: &mut (impl CryptoRng + RngCore),
321 base: &KeyFragBase<'_>,
322 sign_delegating_key: bool,
323 sign_receiving_key: bool,
324 ) -> Self {
325 Self {
326 kfrag: KeyFrag::from_base(rng, base, sign_delegating_key, sign_receiving_key),
327 }
328 }
329
330 pub fn unverify(self) -> KeyFrag {
335 self.kfrag
336 }
337}
338
339#[cfg(feature = "default-serialization")]
340impl DefaultSerialize for VerifiedKeyFrag {}
341
342pub(crate) struct KeyFragBase<'a> {
343 signer: &'a Signer,
344 precursor: CurvePoint,
345 dh_point: CurvePoint,
346 params: Parameters,
347 delegating_pk: PublicKey,
348 receiving_pk: PublicKey,
349 coefficients: Box<[SecretBox<NonZeroCurveScalar>]>,
350}
351
352impl<'a> KeyFragBase<'a> {
353 pub fn new(
354 rng: &mut (impl CryptoRng + RngCore),
355 delegating_sk: &SecretKey,
356 receiving_pk: &PublicKey,
357 signer: &'a Signer,
358 threshold: usize,
359 ) -> Self {
360 let g = CurvePoint::generator();
361 let params = Parameters::new();
362
363 let delegating_pk = delegating_sk.public_key();
364
365 let receiving_pk_point = receiving_pk.to_point();
366
367 let private_precursor = SecretBox::new(NonZeroCurveScalar::random(rng));
370 let precursor = &g * private_precursor.as_secret();
371
372 let dh_point = &receiving_pk_point * private_precursor.as_secret();
373
374 let d = hash_to_shared_secret(&precursor, &receiving_pk_point, &dh_point);
376
377 let coefficient0 =
379 SecretBox::new(delegating_sk.to_secret_scalar().as_secret() * &(d.invert()));
380
381 let mut coefficients = Vec::<SecretBox<NonZeroCurveScalar>>::with_capacity(threshold);
382 coefficients.push(coefficient0);
383 for _i in 1..threshold {
384 coefficients.push(SecretBox::new(NonZeroCurveScalar::random(rng)));
385 }
386
387 Self {
388 signer,
389 precursor,
390 dh_point,
391 params,
392 delegating_pk,
393 receiving_pk: *receiving_pk,
394 coefficients: coefficients.into_boxed_slice(),
395 }
396 }
397}
398
399fn poly_eval(coeffs: &[SecretBox<NonZeroCurveScalar>], x: &NonZeroCurveScalar) -> CurveScalar {
401 let mut result: SecretBox<CurveScalar> =
402 SecretBox::new(coeffs[coeffs.len() - 1].as_secret().into());
403 for i in (0..coeffs.len() - 1).rev() {
404 let temp = SecretBox::new(result.as_secret() * x);
406 *result.as_mut_secret() = temp.as_secret() + coeffs[i].as_secret();
407 }
408 *result.as_secret()
410}
411
412#[cfg(test)]
413mod tests {
414
415 use alloc::boxed::Box;
416
417 use rand_core::OsRng;
418
419 use super::{KeyFragBase, KeyFragVerificationError, VerifiedKeyFrag};
420
421 use crate::{PublicKey, SecretKey, Signer};
422
423 #[cfg(feature = "serde")]
424 use crate::serde_bytes::tests::check_serialization_roundtrip;
425
426 fn prepare_kfrags(
427 sign_delegating_key: bool,
428 sign_receiving_key: bool,
429 ) -> (PublicKey, PublicKey, PublicKey, Box<[VerifiedKeyFrag]>) {
430 let delegating_sk = SecretKey::random();
431 let delegating_pk = delegating_sk.public_key();
432
433 let signer = Signer::new(SecretKey::random());
434 let verifying_pk = signer.verifying_key();
435
436 let receiving_sk = SecretKey::random();
437 let receiving_pk = receiving_sk.public_key();
438
439 let base = KeyFragBase::new(&mut OsRng, &delegating_sk, &receiving_pk, &signer, 2);
440 let vkfrags = [
441 VerifiedKeyFrag::from_base(&mut OsRng, &base, sign_delegating_key, sign_receiving_key),
442 VerifiedKeyFrag::from_base(&mut OsRng, &base, sign_delegating_key, sign_receiving_key),
443 VerifiedKeyFrag::from_base(&mut OsRng, &base, sign_delegating_key, sign_receiving_key),
444 ];
445
446 (delegating_pk, receiving_pk, verifying_pk, Box::new(vkfrags))
447 }
448
449 #[test]
450 fn test_verify() {
451 for sign_dk in [false, true].iter().copied() {
452 for sign_rk in [false, true].iter().copied() {
453 let (delegating_pk, receiving_pk, verifying_pk, vkfrags) =
454 prepare_kfrags(sign_dk, sign_rk);
455
456 let kfrag = vkfrags[0].clone().unverify();
457
458 for supply_dk in [false, true].iter().copied() {
459 for supply_rk in [false, true].iter().copied() {
460 let maybe_dk = if supply_dk {
461 Some(&delegating_pk)
462 } else {
463 None
464 };
465 let maybe_rk = if supply_rk { Some(&receiving_pk) } else { None };
466 let res = kfrag.clone().verify(&verifying_pk, maybe_dk, maybe_rk);
467
468 let sufficient_dk = !sign_dk || (supply_dk == sign_dk);
469 let sufficient_rk = !sign_rk || (supply_rk == sign_rk);
470
471 if sufficient_dk && sufficient_rk {
472 assert!(res.is_ok());
473 assert_eq!(res.unwrap().kfrag, kfrag);
474 } else if !sufficient_dk {
475 assert_eq!(
476 res,
477 Err((
478 KeyFragVerificationError::DelegatingKeyNotProvided,
479 kfrag.clone()
480 ))
481 );
482 } else if !sufficient_rk {
483 assert_eq!(
484 res,
485 Err((
486 KeyFragVerificationError::ReceivingKeyNotProvided,
487 kfrag.clone()
488 ))
489 );
490 }
491 }
492 }
493 }
494 }
495 }
496
497 #[cfg(feature = "serde")]
498 #[test]
499 fn test_serde_serialization() {
500 let (_delegating_pk, _receiving_pk, _verifying_pk, verified_kfrags) =
501 prepare_kfrags(true, true);
502
503 let kfrag = verified_kfrags[0].clone().unverify();
504
505 let kfrag_bytes = rmp_serde::to_vec(&kfrag).unwrap();
507 let vkfrag_bytes = rmp_serde::to_vec(&verified_kfrags[0]).unwrap();
508 assert_eq!(vkfrag_bytes, kfrag_bytes);
509
510 check_serialization_roundtrip(&kfrag);
511 }
512}