1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc = include_str!("../README.md")]
3#![no_std]
4
5use core::ops::{Deref, DerefMut};
6extern crate alloc;
7use alloc::vec::Vec;
8
9use zeroize::Zeroizing;
10
11use ciphersuite::Ciphersuite;
12
13pub use dkg::*;
14
15#[derive(Clone, PartialEq, Eq, Debug, thiserror::Error)]
18pub enum RecoveryError {
19 #[error("no keys provided")]
21 NoKeysProvided,
22 #[error("not enough keys provided (threshold required {required}, provided {provided})")]
24 NotEnoughKeysProvided { required: u16, provided: usize },
25 #[error("keys had inconsistent parameters")]
27 InconsistentParameters,
28 #[error("recovery failed")]
30 Failure,
31 #[error("error from dkg ({0})")]
33 DkgError(DkgError),
34}
35
36pub fn recover_key<C: Ciphersuite>(
38 keys: &[ThresholdKeys<C>],
39) -> Result<Zeroizing<C::F>, RecoveryError> {
40 let included = keys.iter().map(|keys| keys.params().i()).collect::<Vec<_>>();
41
42 let keys_len = keys.len();
43 let mut keys = keys.iter();
44 let first_keys = keys.next().ok_or(RecoveryError::NoKeysProvided)?;
45 {
46 let t = first_keys.params().t();
47 if keys_len < usize::from(t) {
48 Err(RecoveryError::NotEnoughKeysProvided { required: t, provided: keys_len })?;
49 }
50 }
51 {
52 let first_params = (
53 first_keys.params().t(),
54 first_keys.params().n(),
55 first_keys.group_key(),
56 first_keys.current_scalar(),
57 first_keys.current_offset(),
58 );
59 for keys in keys.clone() {
60 let params = (
61 keys.params().t(),
62 keys.params().n(),
63 keys.group_key(),
64 keys.current_scalar(),
65 keys.current_offset(),
66 );
67 if params != first_params {
68 Err(RecoveryError::InconsistentParameters)?;
69 }
70 }
71 }
72
73 let mut res: Zeroizing<_> =
74 first_keys.view(included.clone()).map_err(RecoveryError::DkgError)?.secret_share().clone();
75 for keys in keys {
76 *res.deref_mut() +=
77 keys.view(included.clone()).map_err(RecoveryError::DkgError)?.secret_share().deref();
78 }
79
80 if (C::generator() * res.deref()) != first_keys.group_key() {
81 Err(RecoveryError::Failure)?;
82 }
83
84 Ok(res)
85}