devolutions_crypto/secret_sharing/
secret_sharing_v1.rs1use super::Error;
3use super::Result;
4
5use std::convert::TryFrom;
6
7use rand::rngs::OsRng;
8
9use blahaj::{Share, Sharks};
10use zeroize::Zeroizing;
11
12#[cfg(feature = "fuzz")]
13use arbitrary::Arbitrary;
14
15#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
19#[derive(Clone)]
20pub struct ShareV1 {
21 threshold: u8,
22 share: Share,
23}
24
25impl core::fmt::Debug for ShareV1 {
26 fn fmt(&self, f: &mut core::fmt::Formatter) -> std::result::Result<(), core::fmt::Error> {
27 write!(f, "Share with threshold {}", self.threshold)
28 }
29}
30
31impl From<ShareV1> for Vec<u8> {
32 fn from(share: ShareV1) -> Vec<u8> {
33 let mut data: Vec<u8> = vec![share.threshold];
34 data.append(&mut (&share.share).into());
35
36 data
37 }
38}
39
40impl TryFrom<&[u8]> for ShareV1 {
41 type Error = Error;
42
43 fn try_from(data: &[u8]) -> Result<ShareV1> {
44 if data.len() < 3 {
45 return Err(Error::InvalidLength);
46 };
47
48 let threshold = data[0];
49
50 let share = match Share::try_from(&data[1..]) {
51 Ok(s) => s,
52 Err(_) => return Err(Error::InvalidData),
53 };
54
55 Ok(ShareV1 { threshold, share })
56 }
57}
58
59impl ShareV1 {
60 pub fn generate_shared_key(
61 n_shares: u8,
62 threshold: u8,
63 length: usize,
64 ) -> Result<impl Iterator<Item = ShareV1>> {
65 if n_shares < threshold {
66 return Err(Error::NotEnoughShares);
67 }
68
69 let secret = Zeroizing::new(crate::utils::generate_key(length));
70 let sharks = Sharks(threshold);
71 let dealer = sharks.dealer_rng(&secret, &mut OsRng);
72
73 Ok(dealer.take(n_shares as usize).map(move |s| ShareV1 {
74 threshold,
75 share: s,
76 }))
77 }
78
79 pub fn join_shares<'a, I, J>(shares: I) -> Result<Vec<u8>>
80 where
81 I: IntoIterator<Item = &'a ShareV1, IntoIter = J>,
82 J: Iterator<Item = &'a ShareV1> + Clone,
83 {
84 let shares = shares.into_iter();
85 let threshold = match shares.clone().peekable().peek() {
86 Some(x) => x.threshold,
87 None => return Err(Error::NotEnoughShares),
88 };
89
90 let sharks = Sharks(threshold);
91
92 let shares = shares.map(|s| &s.share);
93 match sharks.recover(shares) {
94 Ok(x) => Ok(x),
95 Err(_) => Err(Error::NotEnoughShares),
96 }
97 }
98}